1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmtestenv/mmtestfw/Source/TestFramework/parseline.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,2274 @@
1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// This module contains CParseLine and CSuiteDll classes
1.18 +// CParseLine contains the functions required to execute
1.19 +// a line of test script file.
1.20 +// CSuiteDll objects contains information about test suite
1.21 +// dlls that have been loaded.
1.22 +//
1.23 +//
1.24 +
1.25 +// system includes
1.26 +#include <f32file.h>
1.27 +
1.28 +// test system includes
1.29 +#include "TestFramework.h"
1.30 +#include "script.h"
1.31 +#include "parseline.h"
1.32 +#include "Filename.h"
1.33 +
1.34 +#include "parseline.inl"
1.35 +
1.36 +const TInt KTimeIncrement = 100*1000000; // max wait interval in micro-seconds (100s)
1.37 +const TUint KMaxThreadAttempts = 128; // max number of times to attempt to create a thread
1.38 +
1.39 +/**
1.40 + *
1.41 + * File path literals
1.42 + *
1.43 + * @xxxx
1.44 + *
1.45 + */
1.46 +_LIT(KTxtDLLpath, "c:\\;c:\\system\\libs;d:\\;d:\\system\\libs;e:\\;e:\\system\\libs;z:\\;z:\\system\\libs");
1.47 +
1.48 +/**
1.49 + *
1.50 + * Script parameter defaults
1.51 + *
1.52 + * @xxxx
1.53 + *
1.54 + */
1.55 +//const TInt KTestGuardTimerDefault = 1000L; // EABI warning removal
1.56 +const TInt KPanicGuardTimerDefault = 1000000L;
1.57 +const TInt KPanicExitReasonDefault = 0;
1.58 +
1.59 +/**
1.60 + *
1.61 + * CParseLine first-phase constructor
1.62 + *
1.63 + * @xxxx
1.64 + *
1.65 + */
1.66 +CParseLine::CParseLine(const TDesC& aMatchString)
1.67 + :iTestVerdict(EPass), iMatchString(aMatchString)
1.68 + {
1.69 + }
1.70 +
1.71 +/**
1.72 + *
1.73 + * CParseLine second-phase constructor
1.74 + *
1.75 + * @param "CScript* aScript"
1.76 + * The script to be parsed
1.77 + *
1.78 + * @param "CTestUtils* aTestUtils"
1.79 + * The TestUtils object to use
1.80 + *
1.81 + * @param "CLog* aLog"
1.82 + * The logger to use
1.83 + *
1.84 + * @xxxx
1.85 + *
1.86 + */
1.87 +void CParseLine::ConstructL(CScript* aScript, CTestUtils* aTestUtils, CLog* aLog, TInt64 aGuardTimer)
1.88 + {
1.89 + // create a new Array to store the test steps in
1.90 + iArrayLoadedSuiteDll = new(ELeave) CArrayPtrFlat<CSuiteDll>(1);
1.91 +
1.92 + iScript = aScript;
1.93 + iTestUtils = aTestUtils;
1.94 + iLog = aLog;
1.95 + iGuardTimer = aGuardTimer;
1.96 + iSeverity = ESevrAll;
1.97 + iBreakOnError = EFalse;
1.98 + }
1.99 +
1.100 +/**
1.101 + *
1.102 + * CParseLine static constructor
1.103 + *
1.104 + * @param "CScript* aScript"
1.105 + * The script to be parsed
1.106 + *
1.107 + * @param "CTestUtils* aTestUtils"
1.108 + * The TestUtils object to use
1.109 + *
1.110 + * @param "CLog* aLog"
1.111 + * The logger to use
1.112 + *
1.113 + * @xxxx
1.114 + *
1.115 + */
1.116 +CParseLine* CParseLine::NewL(CScript* aScript, CTestUtils* aTestUtils, CLog* aLog, TInt64 aGuardTimer, const TDesC& aMatchString)
1.117 + {
1.118 + CParseLine* self = new(ELeave) CParseLine(aMatchString);
1.119 + CleanupStack::PushL(self);
1.120 + self->ConstructL(aScript, aTestUtils, aLog, aGuardTimer);
1.121 + CleanupStack::Pop();
1.122 + return self;
1.123 + }
1.124 +
1.125 +/**
1.126 + *
1.127 + * CParseLine destructor
1.128 + *
1.129 + * @xxxx
1.130 + *
1.131 + */
1.132 +CParseLine::~CParseLine()
1.133 + {
1.134 +
1.135 + // unload DLLs and their records
1.136 + if (iArrayLoadedSuiteDll)
1.137 + {
1.138 + // delete all objects in iArrayLoadedSuiteDll
1.139 + // the destructors will unload any loaded DLLS
1.140 + iArrayLoadedSuiteDll->ResetAndDestroy();
1.141 + delete iArrayLoadedSuiteDll;
1.142 + }
1.143 +
1.144 + }
1.145 +
1.146 +/**
1.147 + *
1.148 + * Process a single line from the script file.
1.149 + *
1.150 + * @param "const TDesC8& aNarrowline"
1.151 + * The script line
1.152 + *
1.153 + * @param "TInt8 aLineNo"
1.154 + * The script line number
1.155 + *
1.156 + * @xxxx
1.157 + *
1.158 + */
1.159 +void CParseLine::ProcessLineL(const TDesC8& aNarrowline, TInt aLineNo)
1.160 + {
1.161 + // make a local unicode buffer
1.162 + TPtr16 lineBuf(REINTERPRET_CAST(TUint16*,User::AllocLC(KMaxLenScriptLine*2)), 0, KMaxLenScriptLine);
1.163 + lineBuf.Fill('\0', KMaxLenScriptLine);
1.164 +
1.165 + // convert the narrow script file to Unicode
1.166 + // TBC find a better way to do this
1.167 + CFileName* testnameU = CFileName::NewLC();
1.168 + testnameU->Copy(aNarrowline);
1.169 +
1.170 + // find the end of the line
1.171 + TInt end = testnameU->Locate('\n');
1.172 +
1.173 + // copy the line into lineBuf
1.174 + if ((end != KErrNotFound) && (end < KMaxLenScriptLine))
1.175 + lineBuf = testnameU->Left(end - 1);
1.176 + else
1.177 + lineBuf = testnameU->FileName();
1.178 +
1.179 + // destroy filename
1.180 + CleanupStack::PopAndDestroy(testnameU);
1.181 +
1.182 + // the parser relies on spaces between tokens. Commas are
1.183 + // allowed but are just replaced with spaces
1.184 + TInt findComma = lineBuf.Locate(TChar(','));
1.185 + while (findComma != KErrNotFound )
1.186 + {
1.187 + // found a comma so replace with space
1.188 + lineBuf.Replace(findComma, 1, _L(" "));
1.189 + findComma = lineBuf.Locate(TChar(','));
1.190 + }
1.191 +
1.192 + // for debugging display the line with a line no
1.193 +#ifdef SCRIPT_DEBUG
1.194 + INFO_PRINTF3(_L("Line:%d %S "), aLineNo, &lineBuf);
1.195 +#endif
1.196 +
1.197 + // if there has been a failure and the user has selected
1.198 + // x then the next commands in the script are skipped until
1.199 + // a test complete statement is found
1.200 + if (iBreakOnError)
1.201 + {
1.202 + if (lineBuf.FindF(_L("TEST_COMPLETE")) == 0)
1.203 + {
1.204 + TestComplete(lineBuf);
1.205 + // reset flag now test complete found
1.206 + iBreakOnError = EFalse;
1.207 + }
1.208 +
1.209 + CleanupStack::PopAndDestroy(); // linebuf
1.210 + // do not process the rest of the line
1.211 + return;
1.212 + }
1.213 +
1.214 + // check the line for command keywords
1.215 + if ((lineBuf.Find(_L("//")) == 0) || (lineBuf.Find(_L("#")) == 0))
1.216 + {
1.217 + // ignore comments
1.218 + }
1.219 + else if (lineBuf.FindF(_L("LOAD_SUITE")) == 0)
1.220 + {
1.221 + LoadSuiteL(lineBuf);
1.222 + }
1.223 + else if (lineBuf.FindF(_L("RUN_SCRIPT")) == 0)
1.224 + {
1.225 + RunScriptL(lineBuf);
1.226 + }
1.227 + else if (lineBuf.FindF(_L("RUN_TEST_STEP")) == 0)
1.228 + {
1.229 + RunTestStep(lineBuf);
1.230 + }
1.231 + else if (lineBuf.FindF(_L("RUN_PANIC_STEP")) == 0)
1.232 + {
1.233 + RunPanicTestStep(lineBuf);
1.234 + }
1.235 + else if (lineBuf.FindF(_L("RUN_TERMINATION_STEP")) == 0)
1.236 + {
1.237 + RunTerminationTestStep(lineBuf);
1.238 + }
1.239 + else if (lineBuf.FindF(_L("RUN_UTILS")) == 0)
1.240 + {
1.241 + RunUtil(lineBuf);
1.242 + }
1.243 + else if (lineBuf.FindF(_L("RUN_PROGRAM")) == 0)
1.244 + {
1.245 + RunProgram(lineBuf);
1.246 + }
1.247 + else if (lineBuf.FindF(_L("UNLOAD")) == 0)
1.248 + {
1.249 + Unload();
1.250 + }
1.251 + else if (lineBuf.FindF(_L("HEAP_MARK")) == 0)
1.252 + {
1.253 + HeapMark();
1.254 + }
1.255 + else if (lineBuf.FindF(_L("HEAP_CHECK")) == 0)
1.256 + {
1.257 + HeapCheck();
1.258 + }
1.259 + else if (lineBuf.FindF(_L("REQUEST_MARK")) == 0)
1.260 + {
1.261 + RequestMark();
1.262 + }
1.263 + else if (lineBuf.FindF(_L("REQUEST_CHECK")) == 0)
1.264 + {
1.265 + RequestCheck();
1.266 + }
1.267 + else if (lineBuf.FindF(_L("HANDLES_MARK")) == 0)
1.268 + {
1.269 + HandlesMark();
1.270 + }
1.271 + else if (lineBuf.FindF(_L("HANDLES_CHECK")) == 0)
1.272 + {
1.273 + HandlesCheck();
1.274 + }
1.275 + else if (lineBuf.FindF(_L("PRINT")) == 0)
1.276 + {
1.277 + ScriptPrint(lineBuf);
1.278 + }
1.279 + else if (lineBuf.FindF(_L("DELAY")) == 0)
1.280 + {
1.281 + Delay(lineBuf);
1.282 + }
1.283 + else if (lineBuf.FindF(_L("SEVERITY")) == 0)
1.284 + {
1.285 + SetSeverity(lineBuf);
1.286 + }
1.287 + else if (lineBuf.FindF(_L("PAUSE_AT_END")) == 0)
1.288 + {
1.289 + // if implemented, add iScript->iPauseAtEnd = ETrue;
1.290 + WARN_PRINTF1(_L("Warning : PAUSE_AT_END not implemented"));
1.291 + }
1.292 + else if (lineBuf.FindF(_L("MULTITHREAD")) == 0)
1.293 + {
1.294 + WARN_PRINTF1(_L("Warning : MULTITHREAD keyword no longer required"));
1.295 + }
1.296 + else if (lineBuf.FindF(_L("SINGLETHREAD")) == 0)
1.297 + {
1.298 + ERR_PRINTF1(_L("Error : Single thread operation no longer supported"));
1.299 + }
1.300 + else if (lineBuf.FindF(_L("PAUSE")) == 0)
1.301 + {
1.302 + iScript->Pause();
1.303 + }
1.304 + else if (lineBuf.FindF(_L("BREAK_ON_ERROR")) == 0)
1.305 + {
1.306 + // if the current test verdict is not PASS
1.307 + // give the user the chance to quit
1.308 + if ( iTestVerdict != EPass )
1.309 + iBreakOnError = iScript->BreakOnError();
1.310 + }
1.311 + else if (lineBuf.FindF(_L("TEST_COMPLETE")) == 0)
1.312 + {
1.313 + // use Tlex to decode the cmd line
1.314 + TestComplete(lineBuf);
1.315 + }
1.316 + else if (lineBuf.FindF(_L("LOG_SETTINGS")) == 0)
1.317 + {
1.318 + // use Tlex to decode the cmd line
1.319 + LogSettings(lineBuf);
1.320 + }
1.321 + else if (lineBuf.Length() == 0)
1.322 + {
1.323 + // ignore blank lines
1.324 + }
1.325 + else
1.326 + {
1.327 + // failed to decode line
1.328 + ERR_PRINTF3(_L("Error in script line:%d - \'%S\'"), aLineNo, &lineBuf);
1.329 + }
1.330 +
1.331 + CleanupStack::PopAndDestroy(); // linebuf
1.332 + }
1.333 +
1.334 +/**
1.335 + *
1.336 + * Implements the TEST_COMPLETE script command.
1.337 + *
1.338 + * @param "const TDesC& aText"
1.339 + * The script line
1.340 + *
1.341 + * @xxxx
1.342 + *
1.343 + */
1.344 +void CParseLine::TestComplete(const TDesC& aText)
1.345 + {
1.346 + // use Tlex to decode the cmd line
1.347 + TLex lex(aText);
1.348 +
1.349 + // start at the begining
1.350 + TPtrC token = lex.NextToken();
1.351 +
1.352 + // get suite name, if any
1.353 + token.Set(lex.NextToken());
1.354 +
1.355 + if (token.Length() != 0)
1.356 + {
1.357 + TBuf<KMaxLenTestSuiteName> currentSuiteName;
1.358 + currentSuiteName = token;
1.359 +
1.360 + // get step name, if any
1.361 + token.Set(lex.NextToken());
1.362 +
1.363 + if (token.Length() != 0)
1.364 + {
1.365 + iCurrentStepName = token;
1.366 + iCurrentSuiteName = currentSuiteName;
1.367 + }
1.368 + else
1.369 + {
1.370 + // failed to decode line - require 0 or 2 parameters exactly
1.371 + // use last suite/step name, return fail
1.372 + ERR_PRINTF2(_L("Error in script line: \'%S\'"), &aText);
1.373 + iTestVerdict = EFail;
1.374 + }
1.375 + }
1.376 +
1.377 + if (!iSkip)
1.378 + {
1.379 + // add the current result to the script
1.380 + iScript->AddResult(iTestVerdict);
1.381 + }
1.382 +
1.383 + // reset for next test
1.384 + iTestVerdict = EPass;
1.385 + }
1.386 +
1.387 +/**
1.388 + *
1.389 + * Implements the PRINT script command.
1.390 + *
1.391 + * @param "const TDesC& aText"
1.392 + * The script line
1.393 + *
1.394 + * @xxxx
1.395 + *
1.396 + */
1.397 +void CParseLine::ScriptPrint(const TDesC& aText)
1.398 + {
1.399 + // display the text after the PRINT and 1 space = 6
1.400 + INFO_PRINTF2(_L("%s "), (aText.Ptr() + 6));
1.401 + }
1.402 +
1.403 +/**
1.404 + *
1.405 + * Implements the DELAY script command.
1.406 + *
1.407 + * @param "const TDesC& aText"
1.408 + * The script line
1.409 + *
1.410 + * @xxxx
1.411 + *
1.412 + */
1.413 +void CParseLine::Delay(const TDesC& aText)
1.414 + {
1.415 + // if the test has already failed skip the delay
1.416 + if (iTestVerdict != EPass)
1.417 + {
1.418 + WARN_PRINTF1(_L("Skipped delay as test has already failed"));
1.419 + return;
1.420 + }
1.421 +
1.422 + // get the required time for the delay
1.423 + // first get the value as a string
1.424 + TLex timeOut(aText);
1.425 + timeOut.NextToken();
1.426 + TPtrC token = timeOut.NextToken();
1.427 +
1.428 + // convert the value into a TInt
1.429 + TLex lexTime(token);
1.430 + TInt64 guardTimerValue;
1.431 + if (lexTime.Val(guardTimerValue) != KErrNone )
1.432 + {
1.433 + ERR_PRINTF2(_L("Error in guard timer value : could not decode \'%S\' as value"),
1.434 + &token);
1.435 + return;
1.436 + }
1.437 +
1.438 + INFO_PRINTF2(_L("Delay for %ld mS"), guardTimerValue);
1.439 +
1.440 + // wait for the required delay
1.441 + User::After(I64INT(guardTimerValue) * 1000);
1.442 + }
1.443 +
1.444 +/**
1.445 + *
1.446 + * Implements the SEVERITY script command.
1.447 + *
1.448 + * @param "const TDesC& aText"
1.449 + * The script line
1.450 + *
1.451 + * @xxxx
1.452 + *
1.453 + */
1.454 +void CParseLine::SetSeverity(const TDesC& aText)
1.455 + {
1.456 + // get the required time for the delay
1.457 + // first get the value as a string
1.458 + TLex severityOut(aText);
1.459 + severityOut.NextToken();
1.460 + TPtrC token = severityOut.NextToken();
1.461 +
1.462 + // convert the value into a TInt
1.463 + TLex lexSeverity(token);
1.464 + TInt severityValue = ESevrAll;
1.465 + if (lexSeverity.Val(severityValue) != KErrNone)
1.466 + {
1.467 + ERR_PRINTF2(_L("Error in severity level value : could not decode \'%S\' as value"),
1.468 + &token);
1.469 + return;
1.470 + }
1.471 +
1.472 + // check severity value to ensure that only bitmasks in use are set...
1.473 + if(!LogSeverity::IsValid(severityValue))
1.474 + {
1.475 + ERR_PRINTF1(_L("Error in severity value : out of range"));
1.476 + return;
1.477 + }
1.478 + else
1.479 + {
1.480 + iSeverity = severityValue;
1.481 +
1.482 + TInt noOfDlls = iArrayLoadedSuiteDll->Count();
1.483 + for ( TInt i = 0; i < noOfDlls; i++)
1.484 + {
1.485 + CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
1.486 + CTestSuite* testSuite = ptrSuite->Suite();
1.487 + testSuite->SetSeverity(iSeverity);
1.488 + }
1.489 + }
1.490 +
1.491 + INFO_PRINTF2(_L("Severity is set to %d"), severityValue);
1.492 + }
1.493 +
1.494 +/**
1.495 + *
1.496 + * Implements the RUN_SCRIPT script command.
1.497 + *
1.498 + * @param "const TDesC& aText"
1.499 + * The script line
1.500 + *
1.501 + * @xxxx
1.502 + *
1.503 + */
1.504 +void CParseLine::RunScriptL(const TDesC& aText)
1.505 + {
1.506 + // use Tlex to decode the cmd line
1.507 + TLex lex(aText);
1.508 +
1.509 + // start at the begining
1.510 + TPtrC token=lex.NextToken();
1.511 +
1.512 + // step over the keyword
1.513 + token.Set(lex.NextToken());
1.514 +
1.515 + // format for printing
1.516 + INFO_PRINTF2(_L("RUN_SCRIPT %S"), &token);
1.517 +
1.518 + // create a new Script object (but use the current parser
1.519 + // as it has the dll loaded record)
1.520 + CScript* newScript=CScript::NewLC(this, iTestUtils, iLog, iGuardTimer, iMatchString);
1.521 +
1.522 + // read in the script file
1.523 + CFileName* scriptFileName = CFileName::NewLC();
1.524 + *scriptFileName = token;
1.525 +
1.526 + if (newScript->OpenScriptFile(scriptFileName))
1.527 + {
1.528 + // process it
1.529 + iTestVerdict = newScript->ExecuteScriptL();
1.530 +
1.531 + // don't bother logging verdicts for scripts - not really useful
1.532 + // add results from the new script to the owner script
1.533 + iScript->AddResult(newScript);
1.534 + }
1.535 + else
1.536 + {
1.537 + // failed to find script so verdict incloncusive
1.538 + iTestVerdict = EInconclusive;
1.539 + }
1.540 +
1.541 + CleanupStack::PopAndDestroy(scriptFileName);
1.542 + CleanupStack::PopAndDestroy(newScript);
1.543 + }
1.544 +
1.545 +/**
1.546 + *
1.547 + * Implements the RUN_TEST_STEP script command.
1.548 + *
1.549 + * @param "const TDesC& aText"
1.550 + * The script line
1.551 + *
1.552 + * @xxxx
1.553 + *
1.554 + */
1.555 +void CParseLine::RunTestStep(const TDesC& aText)
1.556 + {
1.557 + // use TLex to decode the cmd line
1.558 + TLex lex(aText);
1.559 +
1.560 + // step over keyword
1.561 + lex.NextToken();
1.562 +
1.563 + // get guard timer
1.564 + TPtrC timeout;
1.565 + timeout.Set(lex.NextToken());
1.566 +
1.567 + // get the other parameters
1.568 + TPtrC suite, step, config, name, paramSet;
1.569 + suite.Set(lex.NextToken());
1.570 + step.Set(lex.NextToken());
1.571 + config.Set(lex.NextToken());
1.572 + name.Set(lex.NextToken());
1.573 + if (name.Length()==0)
1.574 + {
1.575 + // name is optional, if not given use step
1.576 + name.Set(step);
1.577 + }
1.578 + paramSet.Set(lex.NextToken());
1.579 + if (paramSet.Length()==0)
1.580 + {
1.581 + // paramSet is optional, if not given use name
1.582 + paramSet.Set(name);
1.583 + }
1.584 +
1.585 + // save the name of the current test suite / step
1.586 + iCurrentSuiteName = suite;
1.587 + iCurrentStepName = name;
1.588 +
1.589 + TVerdict currentTestVerdict;
1.590 +
1.591 + INFO_PRINTF2(_L("<a name=\"%S\"</a>"),&name);
1.592 +
1.593 + if (iMatchString.Length()>0 && name.Match(iMatchString)<0)
1.594 + {
1.595 + // we have a match string but no match - so skip
1.596 + INFO_PRINTF2(_L("TEST_STEP:%S skipped"), &name);
1.597 + iSkip = ETrue;
1.598 + return;
1.599 + }
1.600 +
1.601 + iSkip = EFalse;
1.602 +
1.603 + // convert the guard timer value to a TInt64
1.604 + TLex lexTimeOut(timeout);
1.605 + TInt64 guardTimerValue;
1.606 + if (lexTimeOut.Val(guardTimerValue) != KErrNone)
1.607 + {
1.608 + ERR_PRINTF2(_L("Error in guard timer value: %S"),
1.609 + &timeout);
1.610 + currentTestVerdict = EInconclusive;
1.611 + }
1.612 +
1.613 + else
1.614 + {
1.615 + // override guard timer if necessary
1.616 + if((guardTimerValue == KNoGuardTimer) && (iGuardTimer != KNoGuardTimer))
1.617 + {
1.618 + INFO_PRINTF3(_L("Warning : Guard timer value overridden from %ld to %ld"),
1.619 + guardTimerValue, iGuardTimer);
1.620 + guardTimerValue = iGuardTimer;
1.621 + }
1.622 +
1.623 + // log the start of a test step
1.624 + INFO_PRINTF7(_L("RUN_TEST_STEP:%S (step:%S suite:%S timeout:%ldmS config:%S(%S))"),
1.625 + &name, &step, &suite, guardTimerValue, &config, ¶mSet);
1.626 +
1.627 + // NOTE. Now running multithreaded all the time.
1.628 + currentTestVerdict = DoTestNewThread(suite, step, guardTimerValue, config, paramSet);
1.629 + }
1.630 +
1.631 + TPtrC verdictText = CLog::TestResultText(currentTestVerdict);
1.632 +
1.633 + INFO_PRINTF3(_L("TEST_STEP:%S returned:%S "),
1.634 + &name, &verdictText);
1.635 +
1.636 + // this result is only significant if everything else has passed
1.637 + if (iTestVerdict == EPass)
1.638 + iTestVerdict = currentTestVerdict;
1.639 +
1.640 + }
1.641 +
1.642 +/**
1.643 + *
1.644 + * Implements the RUN_PANIC_STEP script command.
1.645 + *
1.646 + * @param "const TDesC& aText"
1.647 + * The script line
1.648 + *
1.649 + * @xxxx
1.650 + *
1.651 + */
1.652 +void CParseLine::RunPanicTestStep(const TDesC& aText)
1.653 + {
1.654 + // NOTE. RUN_PANIC_STEP now incorporates the panic reason and category
1.655 +
1.656 + // use Tlex to decode the cmd line
1.657 + TLex lex(aText);
1.658 +
1.659 + // start at the begining
1.660 + TPtrC timeout=lex.NextToken();
1.661 +
1.662 + // step over the keyword
1.663 + timeout.Set(lex.NextToken());
1.664 +
1.665 + // get the other parameters
1.666 + TPtrC suite, step;
1.667 + TPtrC category, reason;
1.668 + TPtrC config, name, paramSet;
1.669 +
1.670 + suite.Set(lex.NextToken());
1.671 + step.Set(lex.NextToken());
1.672 + category.Set(lex.NextToken());
1.673 + reason.Set(lex.NextToken());
1.674 + config.Set(lex.NextToken());
1.675 + name.Set(lex.NextToken());
1.676 + if (name.Length()==0)
1.677 + {
1.678 + // name is optional, if not given use step
1.679 + name.Set(step);
1.680 + }
1.681 + paramSet.Set(lex.NextToken());
1.682 + if (paramSet.Length()==0)
1.683 + {
1.684 + // paramSet is optional, if not given use name
1.685 + paramSet.Set(name);
1.686 + }
1.687 +
1.688 + if (iMatchString.Length()>0 && name.Match(iMatchString)<0)
1.689 + {
1.690 + // we have a match string but no match - so skip
1.691 + INFO_PRINTF2(_L("TEST_STEP:%S skipped"), &name);
1.692 + iSkip = ETrue;
1.693 + return;
1.694 + }
1.695 +
1.696 + iSkip = EFalse;
1.697 +
1.698 + // save the name of the current test suite / step
1.699 + iCurrentSuiteName = suite;
1.700 + iCurrentStepName = name;
1.701 +
1.702 + // convert the guard timer value to a TInt
1.703 + TLex lexTimeOut(timeout);
1.704 + TInt64 guardTimerValue;
1.705 + if (lexTimeOut.Val(guardTimerValue) != KErrNone)
1.706 + {
1.707 + ERR_PRINTF3(_L("Error in guard timer value:%S using default %dmS"),
1.708 + &timeout, KPanicGuardTimerDefault);
1.709 + guardTimerValue = KPanicGuardTimerDefault;
1.710 + }
1.711 +
1.712 + // convert the exitReason value to a TInt
1.713 + TLex lexReason(reason);
1.714 + TInt exitReason;
1.715 + if (lexReason.Val(exitReason) != KErrNone)
1.716 + {
1.717 + ERR_PRINTF3(_L("Error in exitReason value:%S using default %d"),
1.718 + &reason, KPanicExitReasonDefault);
1.719 + exitReason = KPanicExitReasonDefault;
1.720 + }
1.721 +
1.722 + // override guard timer if necessary
1.723 + if((guardTimerValue == KNoGuardTimer) && (iGuardTimer != KNoGuardTimer))
1.724 + {
1.725 + INFO_PRINTF3(_L("Warning : Guard timer value overridden from %ld to %ld"),
1.726 + guardTimerValue, iGuardTimer);
1.727 + guardTimerValue = iGuardTimer;
1.728 + }
1.729 +
1.730 + // log the start of a test step
1.731 + INFO_PRINTF9(_L("RUN_PANIC_STEP:%S (step:%S suite:%S timeout:%ldmS category:%S reason:%d config:%S(%S))"),
1.732 + &name, &step, &suite, guardTimerValue, &category, exitReason, &config, ¶mSet);
1.733 +
1.734 + // run the test step
1.735 + TVerdict currentTestVerdict;
1.736 +
1.737 + // now running multithreaded all the time
1.738 + currentTestVerdict = DoPanicTest(suite, step, guardTimerValue,
1.739 + category, exitReason, config, paramSet);
1.740 +
1.741 + TPtrC verdictText = CLog::TestResultText(currentTestVerdict);
1.742 + INFO_PRINTF3(_L("TEST_STEP:%S returned:%S "),
1.743 + &name, &verdictText);
1.744 +
1.745 + // this result is only significant if every thing else has passed
1.746 + if (iTestVerdict == EPass)
1.747 + iTestVerdict = currentTestVerdict;
1.748 +
1.749 + }
1.750 +
1.751 +/**
1.752 + *
1.753 + * Implements the RUN_TERMINATION_STEP script command.
1.754 + *
1.755 + * @param "const TDesC& aText"
1.756 + * The script line
1.757 + *
1.758 + * @xxxx
1.759 + *
1.760 + */
1.761 +void CParseLine::RunTerminationTestStep(const TDesC& aText)
1.762 + {
1.763 + // use Tlex to decode the cmd line
1.764 + TLex lex(aText);
1.765 +
1.766 + // start at the begining
1.767 + TPtrC timeout=lex.NextToken();
1.768 +
1.769 + // step over the keyword
1.770 + timeout.Set(lex.NextToken());
1.771 +
1.772 + // get the other parameters
1.773 + TPtrC suite, step;
1.774 + TPtrC reason;
1.775 + TPtrC config;
1.776 +
1.777 + suite.Set(lex.NextToken());
1.778 + step.Set(lex.NextToken());
1.779 + reason.Set(lex.NextToken());
1.780 + config.Set(lex.NextToken());
1.781 +
1.782 + // save the name of the current test suite / step
1.783 + iCurrentSuiteName = suite;
1.784 + iCurrentStepName = step;
1.785 +
1.786 + // convert the guard timer value to a TInt
1.787 + TLex lexTimeOut(timeout);
1.788 + TInt64 guardTimerValue;
1.789 + if (lexTimeOut.Val(guardTimerValue) != KErrNone)
1.790 + {
1.791 + ERR_PRINTF3(_L("Error in guard timer value:%S using default %dmS"),
1.792 + &timeout, KPanicGuardTimerDefault);
1.793 + guardTimerValue = KPanicGuardTimerDefault;
1.794 + }
1.795 +
1.796 + // convert the exitReason value to a TInt
1.797 + TLex lexReason(reason);
1.798 + TInt exitReason;
1.799 + if (lexReason.Val(exitReason) != KErrNone)
1.800 + {
1.801 + ERR_PRINTF3(_L("Error in exitReason value:%S using default %d"),
1.802 + &reason, KPanicExitReasonDefault);
1.803 + exitReason = KPanicExitReasonDefault;
1.804 + }
1.805 +
1.806 + // override guard timer if necessary
1.807 + if((guardTimerValue == KNoGuardTimer) && (iGuardTimer != KNoGuardTimer))
1.808 + {
1.809 + INFO_PRINTF3(_L("Warning : Guard timer value overridden from %ld to %ld"),
1.810 + guardTimerValue, iGuardTimer);
1.811 + guardTimerValue = iGuardTimer;
1.812 + }
1.813 +
1.814 + // log the start of a test step
1.815 + INFO_PRINTF6(_L("RUN_TERMINATION_STEP:%S suite:%S timeout:%ldmS reason:%d config:%S"),
1.816 + &step, &suite, guardTimerValue, exitReason, &config);
1.817 +
1.818 + // run the test step
1.819 + TVerdict currentTestVerdict;
1.820 +
1.821 + // now running multithreaded all the time
1.822 + currentTestVerdict = DoTerminationTest(suite, step, guardTimerValue,
1.823 + exitReason, config);
1.824 +
1.825 + TPtrC verdictText = CLog::TestResultText(currentTestVerdict);
1.826 + INFO_PRINTF3(_L("TEST_STEP:%S returned:%S "),
1.827 + &step, &verdictText);
1.828 +
1.829 + // this result is only significant if every thing else has passed
1.830 + if (iTestVerdict == EPass)
1.831 + iTestVerdict = currentTestVerdict;
1.832 +
1.833 + }
1.834 +
1.835 +/**
1.836 + *
1.837 + * Implements the RUN_UTILS script command.
1.838 + *
1.839 + * @param "const TDesC& aText"
1.840 + * The script line
1.841 + *
1.842 + * @xxxx
1.843 + *
1.844 + */
1.845 +void CParseLine::RunUtil(const TDesC& aText)
1.846 + {
1.847 + // Call the utils
1.848 + iTestUtils->RunUtils(aText);
1.849 + }
1.850 +
1.851 +/**
1.852 + *
1.853 + * Implements the REBOOT script command.
1.854 + *
1.855 + * @param "const TDesC& aText"
1.856 + * The script line
1.857 + *
1.858 + * @xxxx
1.859 + *
1.860 + */
1.861 +void CParseLine::Reboot()
1.862 + {
1.863 + WARN_PRINTF1(_L("Warning : REBOOT command not implemented"));
1.864 + }
1.865 +
1.866 +/**
1.867 + *
1.868 + * Static function to call DoTestStep which is run
1.869 + * in a separate thread
1.870 + *
1.871 + * @param "TAny* aPtr"
1.872 + * The test step data
1.873 + *
1.874 + * @return "TInt"
1.875 + * EPOC error code
1.876 + *
1.877 + * @xxxx
1.878 + *
1.879 + */
1.880 +TInt CParseLine::ThreadFunctionL(TAny* aPtr)
1.881 + {
1.882 + TInt result = KErrNone;
1.883 +
1.884 + // get clean-up stack
1.885 + CTrapCleanup* trapCleanup = CTrapCleanup::New();
1.886 +
1.887 + TRAPD(err, result = ThreadTrapFunctionL(aPtr));
1.888 +
1.889 + delete trapCleanup;
1.890 + return((err != KErrNone) ? err : result);
1.891 + }
1.892 +
1.893 +/**
1.894 + *
1.895 + * Main function to call DoTestStep, called from within
1.896 + * a trap
1.897 + *
1.898 + * @param "TAny* aPtr"
1.899 + * The test step data
1.900 + *
1.901 + * @return "TInt"
1.902 + * EPOC error code
1.903 + *
1.904 + * @xxxx
1.905 + *
1.906 + */
1.907 +TInt CParseLine::ThreadTrapFunctionL(TAny* aPtr)
1.908 + {
1.909 + // get the data for the test
1.910 + CStepData* data = REINTERPRET_CAST(CStepData*, aPtr);
1.911 + CSuiteDll* suiteDll = data->SuiteDll();
1.912 + CTestSuite* testSuite = suiteDll->Suite();
1.913 +
1.914 + // setup local logger
1.915 + CLog* logClient = CLog::NewLC();
1.916 + logClient->OpenLogFileL();
1.917 + testSuite->SetLogSystem(logClient);
1.918 +
1.919 + // do the test step
1.920 + TVerdict result = testSuite->DoTestStep(data->Step(), data->Config(), data->ParamSet());
1.921 +
1.922 + // NB it is the CALLING program's responsibility to save/restore the logger.
1.923 + // If the thread terminates prematurely, the logger is in an undefined state.
1.924 +
1.925 + CleanupStack::PopAndDestroy(logClient);
1.926 + testSuite->SetLogSystem(NULL);
1.927 +
1.928 + // return the test result
1.929 + return result;
1.930 + }
1.931 +
1.932 +/**
1.933 + *
1.934 + * Do a test step in a new thread.
1.935 + *
1.936 + * @param "const TDesC& aSuite"
1.937 + * The test suite
1.938 + *
1.939 + * @param "const TDesC& aStep"
1.940 + * The test step
1.941 + *
1.942 + * @param "TInt aGuardTimerValue"
1.943 + * The guard timer value
1.944 + *
1.945 + * @param "const TDesC& aConfig"
1.946 + * The config data
1.947 + *
1.948 + * @return "TVerdict"
1.949 + * The test result
1.950 + *
1.951 + * @xxxx
1.952 + *
1.953 + */
1.954 +TVerdict CParseLine::DoTestNewThread(const TDesC& aSuite, const TDesC& aStep,
1.955 + TInt64 aGuardTimerValue, const TDesC& aConfig, const TDesC& aParamSet)
1.956 + {
1.957 + // get the number of suites loaded
1.958 + TInt noOfDlls = iArrayLoadedSuiteDll->Count();
1.959 +
1.960 + // search the list of loaded test suite DLLs for the required one
1.961 + for (TInt i = 0; i < noOfDlls; i++)
1.962 + {
1.963 + CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
1.964 + TPtrC name = ptrSuite->Name();
1.965 +
1.966 + if (name.FindF(aSuite)!= KErrNotFound)
1.967 + {
1.968 + // reset step status
1.969 + CTestSuite* testSuite = ptrSuite->Suite();
1.970 + testSuite->SetStepStatus(EStepStatusNone);
1.971 +
1.972 + // store old log status, for restore at thread exit
1.973 + // NB we must do this here, as if thread times out, the log
1.974 + // is in an undefined state
1.975 + CLog* oldLogger = testSuite->LogSystem();
1.976 +
1.977 + CStepData* data = NULL;
1.978 + TRAPD(err, data = CStepData::NewL(aStep, aConfig, aParamSet, ptrSuite));
1.979 + if (err != KErrNone)
1.980 + {
1.981 + ERR_PRINTF2(_L("CStepData::NewL() left with error %d : unable to create test data!"), err);
1.982 + return EFail;
1.983 + }
1.984 +
1.985 + // get step's own stack and heap sizes
1.986 + TInt theHeapSize = KMaxTestThreadHeapSize;
1.987 + TInt theStackSize = KTestStackSize;
1.988 + GetHeapAndStackSize(data, &theHeapSize, &theStackSize);
1.989 +
1.990 + TInt res = KErrAlreadyExists;
1.991 + RThread newThread;
1.992 +
1.993 + TPtrC threadBaseName(_L("DoTestThread"));
1.994 + TBuf<32> threadName;
1.995 +
1.996 + // create a unique named test thread
1.997 + // this will leave if creation is not successful
1.998 + TRAP (res, CreateUniqueTestThreadL( threadBaseName,
1.999 + threadName,
1.1000 + newThread,
1.1001 + ThreadFunctionL,
1.1002 + theStackSize,
1.1003 + KMinHeapSize,
1.1004 + theHeapSize,
1.1005 + data ) );
1.1006 +
1.1007 +
1.1008 + if (res != KErrNone)
1.1009 + {
1.1010 + ERR_PRINTF2(_L("CreateUniqueTestThreadL() left with error %d : unable to create test thread "), res);
1.1011 + delete data;
1.1012 + data = NULL;
1.1013 + return EFail;
1.1014 + }
1.1015 +
1.1016 + // start clock
1.1017 + TTime testStart, testStop;
1.1018 + testStart.HomeTime();
1.1019 +
1.1020 + // start the thread and request the status
1.1021 + TRequestStatus threadStatus;
1.1022 + newThread.Logon(threadStatus);
1.1023 +
1.1024 + // if there is no guard timer value, don't time at all
1.1025 + if (aGuardTimerValue == KNoGuardTimer)
1.1026 + {
1.1027 + // no guard timer
1.1028 + newThread.Resume();
1.1029 + User::WaitForRequest(threadStatus);
1.1030 + }
1.1031 + else
1.1032 + {
1.1033 + // wait for either test thread or timer to end
1.1034 + RTimer guardTimer;
1.1035 + guardTimer.CreateLocal(); // create for this thread
1.1036 + TRequestStatus timerStatus;
1.1037 + newThread.Resume();
1.1038 +
1.1039 + // NB now using At() to allow 64-bit timer values
1.1040 + TInt64 guardTimerUsec = aGuardTimerValue * 1000;
1.1041 + TInt64 totalTime = 0;
1.1042 +
1.1043 + for (;;)
1.1044 + {
1.1045 + if (totalTime>=guardTimerUsec) // timeout has occured
1.1046 + break;
1.1047 + TInt timeout;
1.1048 +
1.1049 + if (totalTime+KTimeIncrement >= guardTimerUsec)
1.1050 + {
1.1051 + TInt64 temp = guardTimerUsec-totalTime;
1.1052 + timeout = I64INT(temp);
1.1053 + }
1.1054 + else
1.1055 + timeout = KTimeIncrement;
1.1056 + totalTime += timeout;
1.1057 + guardTimer.After(timerStatus, timeout);
1.1058 + User::WaitForRequest(threadStatus, timerStatus);
1.1059 + if (threadStatus!=KRequestPending) // normal exit
1.1060 + break;
1.1061 + }
1.1062 +
1.1063 + guardTimer.Cancel();
1.1064 + guardTimer.Close();
1.1065 + }
1.1066 +
1.1067 + // reset any file server error simulations
1.1068 + RFs fs;
1.1069 + TInt fsError = fs.Connect();
1.1070 + if (fsError == KErrNone)
1.1071 + {
1.1072 + fs.SetErrorCondition(KErrNone);
1.1073 + }
1.1074 + fs.Close();
1.1075 +
1.1076 + // restore logger
1.1077 + testSuite->SetLogSystem(oldLogger);
1.1078 +
1.1079 + // get the test result
1.1080 + TVerdict result = STATIC_CAST(TVerdict, threadStatus.Int());
1.1081 +
1.1082 + // check terminated ok
1.1083 + switch(newThread.ExitType())
1.1084 + {
1.1085 + case EExitTerminate:
1.1086 + case EExitKill:
1.1087 + break;
1.1088 + case EExitPanic:
1.1089 + {
1.1090 + TExitCategoryName exitCategory = newThread.ExitCategory();
1.1091 + TInt exitReason = newThread.ExitReason();
1.1092 + ERR_PRINTF3(_L("Thread had a panic %S:%d"), &exitCategory, exitReason);
1.1093 +
1.1094 + result = EFail;
1.1095 + }
1.1096 + break;
1.1097 + case EExitPending:
1.1098 + // if the thread is still pending then the guard timer must have expired
1.1099 + ERR_PRINTF1(_L("Thread timed out"));
1.1100 + // kill the test step thread
1.1101 + newThread.Kill(1);
1.1102 + // give the OS time to cleanup devices, etc.
1.1103 + // NB if the thread dies, the postamble will NOT run
1.1104 + User::After(2000000);
1.1105 + result = EFail;
1.1106 + break;
1.1107 + default:
1.1108 + break;
1.1109 + }
1.1110 +
1.1111 + // done with the test thread
1.1112 + newThread.Close();
1.1113 +
1.1114 + // stop clock
1.1115 + testStop.HomeTime();
1.1116 +
1.1117 + TUint testDuration = I64INT(testStop.MicroSecondsFrom(testStart).Int64());
1.1118 + testDuration /= 1000; // to microseconds
1.1119 + TUint testDurationMsec = testDuration % 1000;
1.1120 + TUint testDurationSec = testDuration / 1000;
1.1121 + INFO_PRINTF3(_L("Test took %d.%03d sec"), testDurationSec, testDurationMsec);
1.1122 +
1.1123 + // return the test verdict
1.1124 + delete data;
1.1125 + data = NULL;
1.1126 + return result;
1.1127 + }
1.1128 + }
1.1129 +
1.1130 + // the required suite has not been found
1.1131 + ERR_PRINTF3(_L("Error in test step:%S - cannot find suite:%S" ),
1.1132 + &aStep, &aSuite);
1.1133 +
1.1134 + return ETestSuiteError;
1.1135 + }
1.1136 +
1.1137 +/**
1.1138 + *
1.1139 + * Do a test step which is expected to panic.
1.1140 + *
1.1141 + * @param "const TDesC& aSuite"
1.1142 + * The test suite
1.1143 + *
1.1144 + * @param "const TDesC& aStep"
1.1145 + * The test step
1.1146 + *
1.1147 + * @param "TInt aGuardTimerValue"
1.1148 + * The guard timer value
1.1149 + *
1.1150 + * @param "const TExitCategoryName aExitCategory"
1.1151 + * The expected exit category
1.1152 + *
1.1153 + * @param "TInt aExitReason"
1.1154 + * The expected exit reason
1.1155 + *
1.1156 + * @param "const TDesC& aConfig"
1.1157 + * The config data
1.1158 + *
1.1159 + * @return "TVerdict"
1.1160 + * The test result
1.1161 + *
1.1162 + * @xxxx
1.1163 + *
1.1164 + */
1.1165 +TVerdict CParseLine::DoPanicTest(const TDesC& aSuite, const TDesC& aStep, TInt64 aGuardTimerValue,
1.1166 + const TExitCategoryName aExitCategory, TInt aExitReason,
1.1167 + const TDesC& aConfig, const TDesC& aParamSet)
1.1168 + {
1.1169 +
1.1170 + // get the number of suites loaded
1.1171 + TInt noOfDlls = iArrayLoadedSuiteDll->Count();
1.1172 +
1.1173 + // search the list of loaded test suite DLLs for the required one
1.1174 + for (TInt i = 0; i < noOfDlls; i++)
1.1175 + {
1.1176 + CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
1.1177 + TPtrC name = ptrSuite->Name();
1.1178 +
1.1179 + if (name.FindF(aSuite)!= KErrNotFound)
1.1180 + {
1.1181 + // reset step status
1.1182 + CTestSuite* testSuite = ptrSuite->Suite();
1.1183 + testSuite->SetStepStatus(EStepStatusNone);
1.1184 +
1.1185 + // store old log status, for restore at thread exit
1.1186 + // NB we must do this here, as if thread times out, the log
1.1187 + // is in an undefined state
1.1188 + CLog* oldLogger = testSuite->LogSystem();
1.1189 +
1.1190 + CStepData* data = NULL;
1.1191 + TRAPD(err, data = CStepData::NewL(aStep, aConfig, aParamSet, ptrSuite));
1.1192 + if (err != KErrNone)
1.1193 + {
1.1194 + ERR_PRINTF2(_L("CStepData::NewL() left with error %d : unable to create test data!"), err);
1.1195 + return EFail;
1.1196 + }
1.1197 +
1.1198 + // get step's own stack and heap sizes
1.1199 + TInt theHeapSize = KMaxTestThreadHeapSize;
1.1200 + TInt theStackSize = KTestStackSize;
1.1201 + GetHeapAndStackSize(data, &theHeapSize, &theStackSize);
1.1202 +
1.1203 + TInt res = KErrAlreadyExists;
1.1204 + RThread newThread;
1.1205 +
1.1206 + // create a unique test name by appending a counter
1.1207 + TPtrC threadBaseName(_L("DoTestThread"));
1.1208 + TBuf<32> threadName;
1.1209 +
1.1210 + // create a unique named test thread
1.1211 + // this will leave if creation is not successful
1.1212 + TRAP (res, CreateUniqueTestThreadL( threadBaseName,
1.1213 + threadName,
1.1214 + newThread,
1.1215 + ThreadFunctionL,
1.1216 + theStackSize,
1.1217 + KMinHeapSize,
1.1218 + theHeapSize,
1.1219 + data ) );
1.1220 +
1.1221 + if (res != KErrNone)
1.1222 + {
1.1223 + ERR_PRINTF2(_L("CreateUniqueTestThreadL() left with error %d : unable to create test thread "), res);
1.1224 + delete data;
1.1225 + data = NULL;
1.1226 + return EFail;
1.1227 + }
1.1228 +
1.1229 + // start clock
1.1230 + TTime testStart, testStop;
1.1231 + testStart.HomeTime();
1.1232 +
1.1233 + // start the thread and request the status
1.1234 + TRequestStatus threadStatus;
1.1235 + newThread.Logon(threadStatus);
1.1236 +
1.1237 + // if there is no guard timer value, don't time at all
1.1238 + if (aGuardTimerValue == KNoGuardTimer)
1.1239 + {
1.1240 + // no guard timer
1.1241 + newThread.Resume();
1.1242 + User::WaitForRequest(threadStatus);
1.1243 + }
1.1244 + else
1.1245 + {
1.1246 + // wait for either test thread or timer to end
1.1247 + RTimer guardTimer;
1.1248 + guardTimer.CreateLocal(); // create for this thread
1.1249 + TRequestStatus timerStatus;
1.1250 + newThread.Resume();
1.1251 +
1.1252 + // NB now using At() to allow 64-bit timer values
1.1253 + TInt64 guardTimerUsec = aGuardTimerValue * 1000;
1.1254 + TInt64 totalTime = 0;
1.1255 +
1.1256 + for (;;)
1.1257 + {
1.1258 + if (totalTime>=guardTimerUsec) // timeout has occured
1.1259 + break;
1.1260 + TInt timeout;
1.1261 +
1.1262 + if (totalTime+KTimeIncrement >= guardTimerUsec)
1.1263 + {
1.1264 + TInt64 temp = guardTimerUsec-totalTime;
1.1265 + timeout = I64INT(temp);
1.1266 + }
1.1267 + else
1.1268 + timeout = KTimeIncrement;
1.1269 + totalTime += timeout;
1.1270 + guardTimer.After(timerStatus, timeout);
1.1271 + User::WaitForRequest(threadStatus, timerStatus);
1.1272 + if (threadStatus!=KRequestPending) // normal exit
1.1273 + break;
1.1274 + }
1.1275 +
1.1276 + guardTimer.Cancel();
1.1277 + guardTimer.Close();
1.1278 + }
1.1279 +
1.1280 + // restore logger
1.1281 + testSuite->SetLogSystem(oldLogger);
1.1282 +
1.1283 + // get the test result
1.1284 + TVerdict result = STATIC_CAST(TVerdict, threadStatus.Int());
1.1285 +
1.1286 + // check terminated ok
1.1287 + switch(newThread.ExitType())
1.1288 + {
1.1289 + case EExitPanic:
1.1290 + {
1.1291 + TExitCategoryName exitCategory = newThread.ExitCategory();
1.1292 + TInt exitReason = newThread.ExitReason();
1.1293 + if((exitCategory != aExitCategory) || (exitReason != aExitReason && aExitReason != KNoPanicReason) )
1.1294 + {
1.1295 + ERR_PRINTF3(_L("Test step had an unexpected panic %S:%d and failed"),
1.1296 + &exitCategory, exitReason);
1.1297 + result = EFail;
1.1298 + }
1.1299 + else
1.1300 + {
1.1301 + // check here that the panic occurred within the test itself
1.1302 + CTestSuite* testSuite = ptrSuite->Suite();
1.1303 + TTestStepStatus status = testSuite->StepStatus();
1.1304 + switch(status)
1.1305 + {
1.1306 + case EStepStatusPreamble:
1.1307 + {
1.1308 + // thread panicked in the test itself - success
1.1309 + INFO_PRINTF3(_L("Test step had a panic %S:%d and passed"),
1.1310 + &exitCategory, exitReason);
1.1311 + result = EPass;
1.1312 + }
1.1313 + break;
1.1314 + case EStepStatusStart:
1.1315 + {
1.1316 + // thread panicked in preamble
1.1317 + ERR_PRINTF3(_L("Test step had a panic %S:%d in preamble"),
1.1318 + &exitCategory, exitReason);
1.1319 + result = EFail;
1.1320 + }
1.1321 + break;
1.1322 + case EStepStatusTest:
1.1323 + {
1.1324 + // thread panicked in postamble
1.1325 + ERR_PRINTF3(_L("Test step had a panic %S:%d in postamble"),
1.1326 + &exitCategory, exitReason);
1.1327 + result = EFail;
1.1328 + }
1.1329 + break;
1.1330 + default:
1.1331 + {
1.1332 + // thread panicked outside the test
1.1333 + ERR_PRINTF3(_L("Test step had a panic %S:%d outside the test"),
1.1334 + &exitCategory, exitReason);
1.1335 + result = EFail;
1.1336 + }
1.1337 + break;
1.1338 + } // end switch
1.1339 + }
1.1340 + }
1.1341 + break;
1.1342 + case EExitPending:
1.1343 + // if the thread is still pending then the guard timer must have expired
1.1344 + ERR_PRINTF1(_L("Thread timed out"));
1.1345 + // kill the test step thread
1.1346 + newThread.Kill(1);
1.1347 + // give the OS time to cleanup devices, etc.
1.1348 + // NB if the thread dies, the postamble will NOT run
1.1349 + User::After(2000000);
1.1350 + result = EFail;
1.1351 + break;
1.1352 + case EExitTerminate:
1.1353 + case EExitKill:
1.1354 + default:
1.1355 + ERR_PRINTF1(_L("Test did not panic, so failed"));
1.1356 + result = EFail;
1.1357 + break;
1.1358 + }
1.1359 +
1.1360 + // done with the test thread
1.1361 + newThread.Close();
1.1362 +
1.1363 + // stop clock
1.1364 + testStop.HomeTime();
1.1365 +
1.1366 + TUint testDuration = I64INT(testStop.MicroSecondsFrom(testStart).Int64());
1.1367 + testDuration /= 1000; // to microseconds
1.1368 + TUint testDurationMsec = testDuration % 1000;
1.1369 + TUint testDurationSec = testDuration / 1000;
1.1370 + INFO_PRINTF3(_L("Test took %d.%03d sec"), testDurationSec, testDurationMsec);
1.1371 +
1.1372 + // return the test verdict
1.1373 + delete data;
1.1374 + data = NULL;
1.1375 + return result;
1.1376 + }
1.1377 + }
1.1378 +
1.1379 + // the required suite has not been found
1.1380 + ERR_PRINTF3(_L("Error in test step:%S - cannot find suite:%S"),
1.1381 + &aStep, &aSuite );
1.1382 +
1.1383 + return ETestSuiteError;
1.1384 + }
1.1385 +
1.1386 +/**
1.1387 + *
1.1388 + * Do a test step which is expected to terminate.
1.1389 + *
1.1390 + * @param "const TDesC& aSuite"
1.1391 + * The test suite
1.1392 + *
1.1393 + * @param "const TDesC& aStep"
1.1394 + * The test step
1.1395 + *
1.1396 + * @param "TInt aGuardTimerValue"
1.1397 + * The guard timer value
1.1398 + *
1.1399 + * @param "TInt aExitReason"
1.1400 + * The expected exit reason
1.1401 + *
1.1402 + * @param "const TDesC& aConfig"
1.1403 + * The config data
1.1404 + *
1.1405 + * @return "TVerdict"
1.1406 + * The test result
1.1407 + *
1.1408 + * @xxxx
1.1409 + *
1.1410 + */
1.1411 +TVerdict CParseLine::DoTerminationTest(const TDesC& aSuite, const TDesC& aStep, TInt64 aGuardTimerValue,
1.1412 + TInt aExitReason, const TDesC& aConfig)
1.1413 + {
1.1414 +
1.1415 + // get the number of suites loaded
1.1416 + TInt noOfDlls = iArrayLoadedSuiteDll->Count();
1.1417 +
1.1418 + // search the list of loaded test suite DLLs for the required one
1.1419 + for (TInt i = 0; i < noOfDlls; i++)
1.1420 + {
1.1421 + CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
1.1422 + TPtrC name = ptrSuite->Name();
1.1423 +
1.1424 + if (name.FindF(aSuite)!= KErrNotFound)
1.1425 + {
1.1426 + // reset step status
1.1427 + CTestSuite* testSuite = ptrSuite->Suite();
1.1428 + testSuite->SetStepStatus(EStepStatusNone);
1.1429 +
1.1430 + // store old log status, for restore at thread exit
1.1431 + // NB we must do this here, as if thread times out, the log
1.1432 + // is in an undefined state
1.1433 + CLog* oldLogger = testSuite->LogSystem();
1.1434 +
1.1435 + CStepData* data = NULL;
1.1436 + TRAPD(err, data = CStepData::NewL(aStep, aConfig, ptrSuite));
1.1437 + if (err != KErrNone)
1.1438 + {
1.1439 + ERR_PRINTF2(_L("CStepData::NewL() left with error %d : unable to create test data!"), err);
1.1440 + return EFail;
1.1441 + }
1.1442 +
1.1443 + // get step's own stack and heap sizes
1.1444 + TInt theHeapSize = KMaxTestThreadHeapSize;
1.1445 + TInt theStackSize = KTestStackSize;
1.1446 + GetHeapAndStackSize(data, &theHeapSize, &theStackSize);
1.1447 +
1.1448 + TInt res = KErrAlreadyExists;
1.1449 + RThread newThread;
1.1450 +
1.1451 + // create a unique test name by appending a counter
1.1452 + TPtrC threadBaseName(_L("DoTestThread"));
1.1453 + TBuf<32> threadName;
1.1454 +
1.1455 + // create a unique named test thread
1.1456 + // this will leave if creation is not successful
1.1457 + TRAP (res, CreateUniqueTestThreadL( threadBaseName,
1.1458 + threadName,
1.1459 + newThread,
1.1460 + ThreadFunctionL,
1.1461 + theStackSize,
1.1462 + KMinHeapSize,
1.1463 + theHeapSize,
1.1464 + data ) );
1.1465 +
1.1466 + if (res != KErrNone)
1.1467 + {
1.1468 + ERR_PRINTF2(_L("CreateUniqueTestThreadL() left with error %d : unable to create test thread "), res);
1.1469 + delete data;
1.1470 + data = NULL;
1.1471 + return EFail;
1.1472 + }
1.1473 +
1.1474 + // start clock
1.1475 + TTime testStart, testStop;
1.1476 + testStart.HomeTime();
1.1477 +
1.1478 + // start the thread and request the status
1.1479 + TRequestStatus threadStatus;
1.1480 + newThread.Logon(threadStatus);
1.1481 +
1.1482 + // if there is no guard timer value, don't time at all
1.1483 + if (aGuardTimerValue == KNoGuardTimer)
1.1484 + {
1.1485 + // no guard timer
1.1486 + newThread.Resume();
1.1487 + User::WaitForRequest(threadStatus);
1.1488 + }
1.1489 + else
1.1490 + {
1.1491 + // wait for either test thread or timer to end
1.1492 + RTimer guardTimer;
1.1493 + guardTimer.CreateLocal(); // create for this thread
1.1494 + TRequestStatus timerStatus;
1.1495 + newThread.Resume();
1.1496 +
1.1497 + // NB now using At() to allow 64-bit timer values
1.1498 + TInt64 guardTimerUsec = aGuardTimerValue * 1000;
1.1499 + TInt64 totalTime = 0;
1.1500 +
1.1501 + for (;;)
1.1502 + {
1.1503 + if (totalTime>=guardTimerUsec) // timeout has occured
1.1504 + break;
1.1505 + TInt timeout;
1.1506 +
1.1507 + if (totalTime+KTimeIncrement >= guardTimerUsec)
1.1508 + {
1.1509 + TInt64 temp = guardTimerUsec-totalTime;
1.1510 + timeout = I64INT(temp);
1.1511 + }
1.1512 + else
1.1513 + timeout = KTimeIncrement;
1.1514 + totalTime += timeout;
1.1515 + guardTimer.After(timerStatus, timeout);
1.1516 + User::WaitForRequest(threadStatus, timerStatus);
1.1517 + if (threadStatus!=KRequestPending) // normal exit
1.1518 + break;
1.1519 + }
1.1520 +
1.1521 + guardTimer.Cancel();
1.1522 + guardTimer.Close();
1.1523 + }
1.1524 +
1.1525 + // restore logger
1.1526 + testSuite->SetLogSystem(oldLogger);
1.1527 +
1.1528 + // get the test result
1.1529 + TVerdict result = STATIC_CAST(TVerdict, threadStatus.Int());
1.1530 +
1.1531 + // check terminated ok
1.1532 + switch(newThread.ExitType())
1.1533 + {
1.1534 + case EExitTerminate:
1.1535 + case EExitKill:
1.1536 + {
1.1537 + TInt exitReason = newThread.ExitReason();
1.1538 + if(exitReason != aExitReason)
1.1539 + {
1.1540 + ERR_PRINTF2(_L("Test step had an unexpected exit reason:%d and failed"),
1.1541 + exitReason);
1.1542 + result = EFail;
1.1543 + }
1.1544 + else
1.1545 + {
1.1546 + // check here that the panic occurred within the test itself
1.1547 + CTestSuite* testSuite = ptrSuite->Suite();
1.1548 + TTestStepStatus status = testSuite->StepStatus();
1.1549 + switch(status)
1.1550 + {
1.1551 + case EStepStatusPreamble:
1.1552 + {
1.1553 + // thread terminated in the test itself - success
1.1554 + INFO_PRINTF2(_L("Test step had terminated:%d and passed"),
1.1555 + exitReason);
1.1556 + result = EPass;
1.1557 + }
1.1558 + break;
1.1559 + case EStepStatusStart:
1.1560 + {
1.1561 + // thread panicked in preamble
1.1562 + ERR_PRINTF2(_L("Test step had terminated:%d in preamble"),
1.1563 + exitReason);
1.1564 + result = EFail;
1.1565 + }
1.1566 + break;
1.1567 + case EStepStatusTest:
1.1568 + {
1.1569 + // thread panicked in postamble
1.1570 + ERR_PRINTF2(_L("Test step had terminated:%d in postamble"),
1.1571 + exitReason);
1.1572 + result = EFail;
1.1573 + }
1.1574 + break;
1.1575 + default:
1.1576 + {
1.1577 + // thread panicked outside the test
1.1578 + ERR_PRINTF2(_L("Test step had terminated:%d outside the test"),
1.1579 + exitReason);
1.1580 + result = EFail;
1.1581 + }
1.1582 + break;
1.1583 + } // end switch
1.1584 + }
1.1585 + }
1.1586 + break;
1.1587 + case EExitPending:
1.1588 + // if the thread is still pending then the guard timer must have expired
1.1589 + ERR_PRINTF1(_L("Thread timed out"));
1.1590 + // kill the test step thread
1.1591 + newThread.Kill(1);
1.1592 + // give the OS time to cleanup devices, etc.
1.1593 + // NB if the thread dies, the postamble will NOT run
1.1594 + User::After(2000000);
1.1595 + result = EFail;
1.1596 + break;
1.1597 + case EExitPanic:
1.1598 + default:
1.1599 + ERR_PRINTF1(_L("Test did not terminate, so failed"));
1.1600 + result = EFail;
1.1601 + break;
1.1602 + }
1.1603 +
1.1604 + // done with the test thread
1.1605 + newThread.Close();
1.1606 +
1.1607 + // stop clock
1.1608 + testStop.HomeTime();
1.1609 +
1.1610 + TUint testDuration = I64INT(testStop.MicroSecondsFrom(testStart).Int64());
1.1611 + testDuration /= 1000; // to microseconds
1.1612 + TUint testDurationMsec = testDuration % 1000;
1.1613 + TUint testDurationSec = testDuration / 1000;
1.1614 + INFO_PRINTF3(_L("Test took %d.%03d sec"), testDurationSec, testDurationMsec);
1.1615 +
1.1616 + // return the test verdict
1.1617 + delete data;
1.1618 + data = NULL;
1.1619 + return result;
1.1620 + }
1.1621 + }
1.1622 +
1.1623 + // the required suite has not been found
1.1624 + ERR_PRINTF3(_L("Error in test step:%S - cannot find suite:%S"),
1.1625 + &aStep, &aSuite );
1.1626 +
1.1627 + return ETestSuiteError;
1.1628 + }
1.1629 +
1.1630 +/**
1.1631 + *
1.1632 + * Gets a step's heap and stack size.
1.1633 + *
1.1634 + * @param "const CStepData& aStepData"
1.1635 + * The step data
1.1636 + * @param "TInt* aHeapSize"
1.1637 + * Returns the step's heap size
1.1638 + * @param "TInt* aStackSize"
1.1639 + * Returns the step's stack size
1.1640 + *
1.1641 + * @xxxx
1.1642 + *
1.1643 + */
1.1644 +void CParseLine::GetHeapAndStackSize(const CStepData* aStepData, TInt* aHeapSize, TInt* aStackSize)
1.1645 + {
1.1646 + CSuiteDll* suiteDll = aStepData->SuiteDll();
1.1647 + CTestSuite* testSuite = suiteDll->Suite();
1.1648 + testSuite->GetHeapAndStackSize(aStepData->Step(), aHeapSize, aStackSize);
1.1649 + }
1.1650 +
1.1651 +/**
1.1652 + *
1.1653 + * Implements the RUN_PROGRAM script command.
1.1654 + *
1.1655 + * @param "const TDesC& aText"
1.1656 + * The script line
1.1657 + *
1.1658 + * @xxxx
1.1659 + *
1.1660 + */
1.1661 +void CParseLine::RunProgram(const TDesC& aText)
1.1662 + {
1.1663 + TPtrC param;
1.1664 +
1.1665 + // use Tlex to decode the cmd line
1.1666 + TLex lex(aText);
1.1667 +
1.1668 + // step over the keyword
1.1669 + lex.NextToken();
1.1670 +
1.1671 + // get program name
1.1672 + TPtrC token;
1.1673 + token.Set(lex.NextToken());
1.1674 +
1.1675 + // get the parameters
1.1676 + param.Set(lex.NextToken());
1.1677 +
1.1678 + INFO_PRINTF1(_L("Run Program "));
1.1679 +
1.1680 +
1.1681 + // In the ARM build run program as a new process
1.1682 + // use the rest of the text as parameters
1.1683 + RProcess program;
1.1684 + TInt ret = program.Create(token, lex.Remainder());
1.1685 +
1.1686 + if (ret != KErrNone)
1.1687 + {
1.1688 + TPtrC errortxt = CLog::EpocErrorToText(ret);
1.1689 + ERR_PRINTF2(_L("Failed to start process - error %S"), &errortxt);
1.1690 + return;
1.1691 + }
1.1692 + else
1.1693 + {
1.1694 + INFO_PRINTF1(_L("Program started"));
1.1695 +
1.1696 + // start program
1.1697 + TRequestStatus threadStatus;
1.1698 + program.Logon(threadStatus);
1.1699 + program.Resume();
1.1700 +
1.1701 + // wait for guard timer
1.1702 + User::WaitForRequest(threadStatus);
1.1703 +
1.1704 + // check return type
1.1705 + if (program.ExitType() == EExitPanic)
1.1706 + INFO_PRINTF1(_L("Program returned EExitPanic"));
1.1707 + else if (program.ExitType() == EExitPending)
1.1708 + INFO_PRINTF1(_L("Program returned EExitPending"));
1.1709 + else
1.1710 + INFO_PRINTF1(_L("Program returned EExitTerminate"));
1.1711 + }
1.1712 + }
1.1713 +
1.1714 +/**
1.1715 + *
1.1716 + * Implements the LOG_SETTINGS script command.
1.1717 + * Command format is LOG_SETTINGS "put src." (1/0),
1.1718 + * "HTML format" (1/0)
1.1719 + *
1.1720 + * @param "const TDesC& aText"
1.1721 + * The script line
1.1722 + *
1.1723 + * @xxxx
1.1724 + *
1.1725 + */
1.1726 +void CParseLine::LogSettings(const TDesC& aText)
1.1727 + {
1.1728 + // use Tlex to decode the cmd line
1.1729 + TLex lex(aText);
1.1730 +
1.1731 + // start at the begining
1.1732 + TPtrC token=lex.NextToken();
1.1733 +
1.1734 + // step over the keyword
1.1735 + //Get information about source
1.1736 + token.Set(lex.NextToken());
1.1737 +
1.1738 + TLex srcLex(token);
1.1739 + TInt isSrc = ETrue; //Shall we put src information?
1.1740 + if (srcLex.Val(isSrc) != KErrNone)
1.1741 + {
1.1742 + ERR_PRINTF2(_L("Error in LOG_SETTINGS: could not decode >%S< as value(0/1)"),
1.1743 + &token);
1.1744 + }
1.1745 + else
1.1746 + {
1.1747 + iLog->SetPutSrcInfo(isSrc) ;
1.1748 + }
1.1749 + //Get information about format
1.1750 + token.Set(lex.NextToken());
1.1751 + TLex htmlLex(token);
1.1752 +
1.1753 + if (htmlLex.Val(isSrc) != KErrNone)
1.1754 + {
1.1755 + ERR_PRINTF2(_L("Error in LOG_SETTINGS: could not decode >%S< as value(0/1)"),
1.1756 + &token);
1.1757 + }
1.1758 + else
1.1759 + {
1.1760 + iLog->SetHtmlLogMode(isSrc);
1.1761 + }
1.1762 + }
1.1763 +
1.1764 +
1.1765 +/**
1.1766 + *
1.1767 + * Implements the LOAD_SUITE script command.
1.1768 + * This function loads a required test suite DLL
1.1769 + * It also creates a CTestSuite object as a record
1.1770 + * of the loaded DLL.
1.1771 + *
1.1772 + * @param "const TDesC& aText"
1.1773 + * The script line
1.1774 + *
1.1775 + * @xxxx
1.1776 + *
1.1777 + */
1.1778 +void CParseLine::LoadSuiteL(const TDesC& aText)
1.1779 + {
1.1780 + // use Tlex to decode the cmd line
1.1781 + TLex lex(aText);
1.1782 +
1.1783 + // step over the keyword
1.1784 + lex.NextToken();
1.1785 +
1.1786 + // get suite name
1.1787 + TPtrC token;
1.1788 + token.Set(lex.NextToken());
1.1789 +
1.1790 + // check not already loaded
1.1791 + // by searching the list of loaded test suite DLLs for the required one
1.1792 + // start with the number of suites loaded
1.1793 + TInt noOfDlls = iArrayLoadedSuiteDll->Count();
1.1794 + for (TInt i = 0; i < noOfDlls; i++)
1.1795 + {
1.1796 + CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
1.1797 + TPtrC name = ptrSuite->Name();
1.1798 +
1.1799 + // check the names
1.1800 + if (name.FindF(token) != KErrNotFound)
1.1801 + {
1.1802 + // this suite DLL is already loaded
1.1803 + WARN_PRINTF2(_L("Warning: Test suite %S already loaded - not re-loaded"), &token);
1.1804 + return;
1.1805 + }
1.1806 + }
1.1807 +
1.1808 +
1.1809 + // create a new CSuiteDll object to store info on loaded DLL
1.1810 + CSuiteDll* newRef = NULL;
1.1811 +
1.1812 + newRef = CSuiteDll::NewL(token, iLog);
1.1813 +
1.1814 + CTestSuite* testSuite = newRef->Suite();
1.1815 +
1.1816 + // set default severity and logging system
1.1817 + testSuite->SetSeverity(iSeverity);
1.1818 + testSuite->SetLogSystem(iLog);
1.1819 +
1.1820 + // add to data
1.1821 + iArrayLoadedSuiteDll->AppendL(newRef);
1.1822 + }
1.1823 +
1.1824 +
1.1825 +/**
1.1826 + *
1.1827 + * Unload all the loaded DLLs
1.1828 + *
1.1829 + * @xxxx
1.1830 + *
1.1831 + */
1.1832 +void CParseLine::Unload()
1.1833 + {
1.1834 + if (iArrayLoadedSuiteDll)
1.1835 + {
1.1836 + // unload all the loaded DLLS and their records
1.1837 + iArrayLoadedSuiteDll->ResetAndDestroy();
1.1838 + }
1.1839 + }
1.1840 +
1.1841 +/**
1.1842 + *
1.1843 + * Mark the heap
1.1844 + *
1.1845 + * @xxxx
1.1846 + *
1.1847 + */
1.1848 +void CParseLine::HeapMark()
1.1849 + {
1.1850 + ERR_PRINTF1(_L("Warning: Command HEAP_MARK no longer supported. Heap marking/checking should be done within test code"));
1.1851 +
1.1852 + // __UHEAP_MARK;
1.1853 + }
1.1854 +
1.1855 +
1.1856 +/**
1.1857 + *
1.1858 + * Check the heap
1.1859 + *
1.1860 + * @xxxx
1.1861 + *
1.1862 + */
1.1863 +void CParseLine::HeapCheck()
1.1864 + {
1.1865 + ERR_PRINTF1(_L("Warning: Command HEAP_CHECK no longer supported. Heap marking/checking should be done within test code"));
1.1866 +
1.1867 + // __UHEAP_MARKEND;
1.1868 + }
1.1869 +
1.1870 +/**
1.1871 + *
1.1872 + * Mark request
1.1873 + *
1.1874 + * @xxxx
1.1875 + *
1.1876 + */
1.1877 +void CParseLine::RequestMark()
1.1878 + {
1.1879 + // get number of outstanding requetsts on thread before we run the test
1.1880 + iReqsAtStart = RThread().RequestCount();
1.1881 + INFO_PRINTF2(_L("Requests at the start %d "),iReqsAtStart);
1.1882 + }
1.1883 +
1.1884 +
1.1885 +/**
1.1886 + *
1.1887 + * Check request
1.1888 + *
1.1889 + * @xxxx
1.1890 + *
1.1891 + */
1.1892 +void CParseLine::RequestCheck()
1.1893 + {
1.1894 + // check the number of outstanding requests against recorded value
1.1895 + INFO_PRINTF3(_L("Requests at the start %d now %d"),
1.1896 + iReqsAtStart, RThread().RequestCount());
1.1897 +
1.1898 + if (iReqsAtStart != RThread().RequestCount())
1.1899 + {
1.1900 + ERR_PRINTF1(_L("Test failed on requests count"));
1.1901 +
1.1902 + // this result is only significant if every thing else has passed
1.1903 + if (iTestVerdict == EPass)
1.1904 + iTestVerdict = EFail;
1.1905 +
1.1906 + }
1.1907 + }
1.1908 +
1.1909 +
1.1910 +/**
1.1911 + *
1.1912 + * Mark number of handles
1.1913 + *
1.1914 + * @xxxx
1.1915 + *
1.1916 + */
1.1917 +void CParseLine::HandlesMark()
1.1918 + {
1.1919 + // get number of Handles *before* we start the program
1.1920 + RThread().HandleCount(iProcessHandleCountBefore, iThreadHandleCountBefore);
1.1921 +
1.1922 + INFO_PRINTF3(_L("HandlesMark : process handle count %d thread handle count %d"),
1.1923 + iProcessHandleCountBefore,
1.1924 + iThreadHandleCountBefore);
1.1925 + }
1.1926 +
1.1927 +/**
1.1928 + *
1.1929 + * Check number of handles
1.1930 + *
1.1931 + * @xxxx
1.1932 + *
1.1933 + */
1.1934 +void CParseLine::HandlesCheck()
1.1935 + {
1.1936 + TInt processHandleCountAfter;
1.1937 + TInt threadHandleCountAfter;
1.1938 + RThread().HandleCount(processHandleCountAfter, threadHandleCountAfter);
1.1939 +
1.1940 + INFO_PRINTF3(_L("HandlesCheck : process handle count %d thread handle count %d"),
1.1941 + processHandleCountAfter,
1.1942 + threadHandleCountAfter);
1.1943 +
1.1944 + // check that we are closing all the threads
1.1945 + if(iThreadHandleCountBefore != threadHandleCountAfter)
1.1946 + {
1.1947 + ERR_PRINTF1(_L("Test failed on thread handle count"));
1.1948 +
1.1949 + // this result is only significant if everything else has passed
1.1950 + if (iTestVerdict == EPass)
1.1951 + iTestVerdict = EFail;
1.1952 + }
1.1953 +
1.1954 + // check that we are closing all the handles
1.1955 + if(iProcessHandleCountBefore != processHandleCountAfter)
1.1956 + {
1.1957 + ERR_PRINTF1(_L("Test failed on process handle count"));
1.1958 +
1.1959 + // this result is only significant if everything else has passed
1.1960 + if (iTestVerdict == EPass)
1.1961 + iTestVerdict = EFail;
1.1962 + }
1.1963 + }
1.1964 +
1.1965 +/**
1.1966 + *
1.1967 + * Traceable logging function for parseline.
1.1968 + * To be called only with macros
1.1969 + *
1.1970 + * @param "const TText8* aFile"
1.1971 + * Source code file name
1.1972 + *
1.1973 + * @param "TInt aLine"
1.1974 + * Source code line
1.1975 + *
1.1976 + * @param "TInt aSeverity"
1.1977 + * Severity level required to log
1.1978 + *
1.1979 + * @param "TRefByValue<const TDesC16> aFmt"
1.1980 + * Printf-style format.
1.1981 + *
1.1982 + * @param "..."
1.1983 + * Variable print parameters
1.1984 + *
1.1985 + * @xxxx
1.1986 + *
1.1987 + */
1.1988 +void CParseLine::LogExtra(const TText8* aFile, TInt aLine, TInt aSeverity,
1.1989 + TRefByValue<const TDesC16> aFmt,...)
1.1990 + {
1.1991 + VA_LIST aList;
1.1992 + VA_START(aList, aFmt);
1.1993 +
1.1994 + if(LogSeverity::IsActive(aSeverity, iSeverity))
1.1995 + {
1.1996 + if(iLog)
1.1997 + {
1.1998 + iLog->LogExtra(aFile, aLine, aSeverity, aFmt, aList);
1.1999 + }
1.2000 + }
1.2001 +
1.2002 + VA_END(aList);
1.2003 + }
1.2004 +
1.2005 +/**
1.2006 + *
1.2007 + * Get current suite name.
1.2008 + *
1.2009 + * @return "TPtrC"
1.2010 + * The suite name
1.2011 + *
1.2012 + * @xxxx
1.2013 + *
1.2014 + */
1.2015 +TPtrC CParseLine::CurrentSuiteName() const
1.2016 + {
1.2017 + return iCurrentSuiteName;
1.2018 + }
1.2019 +
1.2020 +/**
1.2021 + *
1.2022 + * Get current step name.
1.2023 + *
1.2024 + * @return "TPtrC"
1.2025 + * The step name
1.2026 + *
1.2027 + * @xxxx
1.2028 + *
1.2029 + */
1.2030 +TPtrC CParseLine::CurrentStepName() const
1.2031 + {
1.2032 + return iCurrentStepName;
1.2033 + }
1.2034 +
1.2035 +/**
1.2036 + *
1.2037 + * Create a thread with a unique name from a base thread name
1.2038 + * e.g. "TestThread" may become "TestThread00000002"
1.2039 + * This test will leave instantly if an error other than
1.2040 + * KErrAlreadyExists occurs.
1.2041 + *
1.2042 + *
1.2043 + * @param "TDesC& aBaseName"
1.2044 + * The base name to use. This will be modified to contain
1.2045 + * the new unique thread name if creation is successful.
1.2046 + *
1.2047 + * @param "TDes& aThreadName"
1.2048 + * The thread name to use. This will be modified to contain
1.2049 + * the new unique thread name if creation is successful. This must
1.2050 + * be non NULL.
1.2051 + *
1.2052 + * @param "RThread&"
1.2053 + * An RThread which will be created. This must not be a valid handle.
1.2054 + *
1.2055 + * @param "TThreadFunction aFunction"
1.2056 + * Thread function to use in RThread.
1.2057 + *
1.2058 + * @param "TInt aStackSize"
1.2059 + * The size of the new thread's stack.
1.2060 + *
1.2061 + * @param "TInt aHeapMinSize"
1.2062 + * The minimum size for the new thread's heap.
1.2063 + *
1.2064 + * @param "TInt aHeapMaxSize"
1.2065 + * The maximum size for the new thread's heap.
1.2066 + *
1.2067 + * @param "TAny *aPtr"
1.2068 + * Data to pass to the new thread.
1.2069 + *
1.2070 + * @leave "function will leave with an error code if a thread cannot
1.2071 + * be created after KMaxThreadAttempts tries."
1.2072 + *
1.2073 + * @xxxx
1.2074 + *
1.2075 + */
1.2076 +void CParseLine::CreateUniqueTestThreadL(const TDesC& aBaseName, TDes& aThreadName, RThread& aTestThread, TThreadFunction aFunction, TInt aStackSize, TInt aHeapMinSize, TInt aHeapMaxSize, TAny *aPtr)
1.2077 + {
1.2078 + TInt res = KErrAlreadyExists;
1.2079 +
1.2080 + // attempt to create a thread with the name aBaseName + counter.
1.2081 + for (TUint i = 0; i < KMaxThreadAttempts; i++)
1.2082 + {
1.2083 + // copy the base thread name
1.2084 + aThreadName.Copy(aBaseName);
1.2085 +
1.2086 + // append the current counter to the threadname
1.2087 + aThreadName.AppendNumFixedWidth(i, EDecimal, 8);
1.2088 +
1.2089 + // run in a new thread, with a new heap
1.2090 + res = aTestThread.Create(aThreadName,
1.2091 + aFunction,
1.2092 + aStackSize,
1.2093 + aHeapMinSize,
1.2094 + aHeapMaxSize,
1.2095 + aPtr);
1.2096 +
1.2097 + // if thread created successfully then we have
1.2098 + // a unique threadname else if an error code other
1.2099 + // than KErrAlreadyExists occurs then exit immediately.
1.2100 + if ((res == KErrNone) || (res != KErrAlreadyExists))
1.2101 + break;
1.2102 + }
1.2103 +
1.2104 + User::LeaveIfError(res);
1.2105 + }
1.2106 +
1.2107 +/**
1.2108 + *
1.2109 + * Static constructor for CSuiteDll.
1.2110 + *
1.2111 + *
1.2112 + * @return "CSuiteDll*"
1.2113 + * The constructed CSuiteDll
1.2114 + *
1.2115 + * @xxxx
1.2116 + *
1.2117 + */
1.2118 +CSuiteDll* CSuiteDll::NewL(const TDesC& aName, CLog* aLog)
1.2119 + {
1.2120 + CSuiteDll* self = new(ELeave) CSuiteDll;
1.2121 + CleanupStack::PushL(self);
1.2122 + self->ConstructL(aName, aLog);
1.2123 + CleanupStack::Pop();
1.2124 + return self;
1.2125 + }
1.2126 +
1.2127 +/**
1.2128 + *
1.2129 + * CSuiteDLL second-phase constructor
1.2130 + * Loads a test suite dll and saves the name and test
1.2131 + * suite pointers.
1.2132 + *
1.2133 + * @param "TDesC& aName"
1.2134 + * The test suite name
1.2135 + *
1.2136 + * @param "CLog* aLog"
1.2137 + * The logger to use
1.2138 + *
1.2139 + * @xxxx
1.2140 + *
1.2141 + */
1.2142 +void CSuiteDll::ConstructL(const TDesC& aName, CLog* aLog)
1.2143 + {
1.2144 + iLog = aLog;
1.2145 +
1.2146 + User::Check();
1.2147 + // load DLL by name
1.2148 + TInt ret = iLibrary.Load(aName, KTxtDLLpath);
1.2149 +
1.2150 + User::Check();
1.2151 +
1.2152 + if (ret == KErrNotFound)
1.2153 + {
1.2154 + iLog->LogExtra(__FILE8__, __LINE__, ESevrErr, _L("Test suite %S was not found. Check any other DLLs required by %S"), &aName, &aName);
1.2155 + User::Leave(ret);
1.2156 + }
1.2157 + else if (ret != KErrNone)
1.2158 + {
1.2159 + iLog->LogExtra(__FILE8__, __LINE__, ESevrErr, _L("Test suite %S found but would not load. Check any other DLLs required by %S"), &aName, &aName);
1.2160 + User::Leave(ret);
1.2161 + }
1.2162 +
1.2163 + // save the name
1.2164 + iName.Copy(aName);
1.2165 +
1.2166 + // get the interface pointer at ordinal 1
1.2167 + const TInt KLibraryOrdinal = 1;
1.2168 + TLibraryFunction entryL = iLibrary.Lookup(KLibraryOrdinal);
1.2169 +
1.2170 + // Call this interface pointer to create new CTestSuite
1.2171 + // If this call goes to the wrong function then the test
1.2172 + // suite does not have the correct function at ordinal 1.
1.2173 + // This is usually caused by an error in the def file.
1.2174 + iTestSuite = REINTERPRET_CAST(CTestSuite*, entryL());
1.2175 +
1.2176 + // NB :- Second-phase constructor for CTestSuite has already been called in entryL() above.
1.2177 + // There is no need to call it again!
1.2178 +
1.2179 + // set suite severity level
1.2180 + iTestSuite->SetSeverity(iLog->Severity());
1.2181 +
1.2182 + // get the version information
1.2183 + TPtrC versiontxt = iTestSuite->GetVersion();
1.2184 +
1.2185 + // add to log
1.2186 + iLog->LogExtra(__FILE8__, __LINE__, ESevrInfo, _L("LOAD_SUITE %S version %S loaded ok"),&aName, &versiontxt );
1.2187 + }
1.2188 +
1.2189 +/**
1.2190 + *
1.2191 + * CSuiteDLL destructor
1.2192 + *
1.2193 + * @xxxx
1.2194 + *
1.2195 + */
1.2196 +CSuiteDll::~CSuiteDll()
1.2197 + {
1.2198 + // delete the TestSuiteObject in the loaded DLL
1.2199 + delete iTestSuite;
1.2200 +
1.2201 + // close and unload the library
1.2202 + iLibrary.Close();
1.2203 + }
1.2204 +
1.2205 +/**
1.2206 + *
1.2207 + * CSuiteDLL accessor : suite
1.2208 + *
1.2209 + * @return "CTestSuite*"
1.2210 + * The test suite.
1.2211 + *
1.2212 + * @xxxx
1.2213 + *
1.2214 + */
1.2215 +CTestSuite* CSuiteDll::Suite() const
1.2216 + {
1.2217 + return iTestSuite;
1.2218 + }
1.2219 +
1.2220 +/**
1.2221 + *
1.2222 + * CSuiteDLL accessor : suite name
1.2223 + *
1.2224 + * @return "TPtrC"
1.2225 + * The suite name.
1.2226 + *
1.2227 + * @xxxx
1.2228 + *
1.2229 + */
1.2230 +TPtrC CSuiteDll::Name() const
1.2231 + {
1.2232 + return iName;
1.2233 + }
1.2234 +
1.2235 +/**
1.2236 + *
1.2237 + * CStepData
1.2238 + *
1.2239 + * @xxxx
1.2240 + *
1.2241 + */
1.2242 +CStepData* CStepData::NewL(const TDesC& aStep, const TDesC& aConfig, CSuiteDll* aSuite)
1.2243 + {
1.2244 + return NewL(aStep, aConfig, KNullDesC, aSuite);
1.2245 + }
1.2246 +
1.2247 +CStepData* CStepData::NewL(const TDesC& aStep, const TDesC& aConfig, const TDesC& aParamSet, CSuiteDll* aSuite)
1.2248 + {
1.2249 + CStepData* self = new(ELeave) CStepData;
1.2250 + CleanupStack::PushL(self);
1.2251 + self->ConstructL(aStep, aConfig, aParamSet, aSuite);
1.2252 + CleanupStack::Pop();
1.2253 + return self;
1.2254 + }
1.2255 +
1.2256 +CStepData::CStepData()
1.2257 + {
1.2258 + }
1.2259 +
1.2260 +CStepData::~CStepData()
1.2261 + {
1.2262 + }
1.2263 +
1.2264 +void CStepData::ConstructL(const TDesC& aStep, const TDesC& aConfig, const TDesC& aParamSet, CSuiteDll* aSuite)
1.2265 + {
1.2266 + iStep = aStep;
1.2267 + iConfig = aConfig;
1.2268 + iParamSet = aParamSet;
1.2269 + iSuite = aSuite;
1.2270 + }
1.2271 +
1.2272 +const TDesC& CStepData::ParamSet() const
1.2273 + {
1.2274 + return iParamSet;
1.2275 + }
1.2276 +
1.2277 +