--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagingtestenv/imagingtestfw/Source/TestFramework/script.cpp Wed Aug 25 12:29:52 2010 +0300
@@ -0,0 +1,663 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// This module contains CScript class
+//
+//
+
+// system includes
+#include <f32file.h>
+
+// test system includes
+#include <testframework.h>
+#include "Filename.h"
+#include "script.h"
+#include "parseline.h"
+#include "config.h"
+
+#if !defined (__TSU_TESTFRAMEWORK__)
+/**
+ *
+ * Script files can reference other script files.
+ * KMaxDepthRecursion limits the number of references.
+ * This is to catch accidental circular references in script files
+ * which would otherwise cause the system to continue until all
+ * memory had be used making more CScript objects.
+ *
+ * @xxxx
+ *
+ */
+const TInt KMaxDepthRecursion = 100;
+
+#endif
+
+/**
+ *
+ * Global data : count of how deep in script files parser is.
+ * This is to check against infinite recursion
+ *
+ * NB : we must patch this out for Unit Testing, where script.cpp
+ * is part of a DLL
+ *
+ * @xxxx
+ *
+ */
+// do not define static if Unit Testing
+#if !defined (__TSU_TESTFRAMEWORK__)
+GLDEF_D TInt CScript::iScriptDepth = 0;
+#endif
+
+/**
+ *
+ * Console prompts
+ *
+ * @xxxx
+ *
+ */
+//_LIT(KTxtPressAnyKey,"[press any key to continue]\n"); // EABI warning removal
+//_LIT(KTxtBreakOnError,"The test has failed, press X to terminate this test\n [press any other key to continue]\n"); // EABI warning removal
+
+/**
+ *
+ * CScript first-phase constructor
+ *
+ * @xxxx
+ *
+ */
+CScript::CScript()
+ {
+ }
+
+/**
+ *
+ * CScript second-phase constructor for a script processor which
+ * does not inherit a parser.
+ *
+ * @param "CTestUtils* aTestUtils"
+ * The TestUtils object to use
+ *
+ * @param "CLog* aLog"
+ * The logger to use
+ *
+ * @xxxx
+ *
+ */
+void CScript::ConstructL(CTestUtils* aTestUtils, CLog* aLog, TInt64 aGuardTimer, const TDesC& aMatchString)
+ {
+ iLog = aLog;
+ iGuardTimer = aGuardTimer;
+
+ iMatchString = aMatchString.AllocL();
+
+ iParse = CParseLine::NewL(this, aTestUtils, aLog, aGuardTimer, *iMatchString);
+ iParseOwner = ETrue;
+
+ iPauseAtEnd = EFalse;
+
+#if !defined (__TSU_TESTFRAMEWORK__)
+ iScriptDepth++;
+#endif
+ }
+
+/**
+ *
+ * CScript static constructor for a script processor which
+ * does not inherit a parser.
+ *
+ * @param "CTestUtils* aTestUtils"
+ * The TestUtils object to use
+ *
+ * @param "CLog* aLog"
+ * The logger to use
+ *
+ * @xxxx
+ *
+ */
+CScript* CScript::NewL(CTestUtils* aTestUtils, CLog * aLog, TInt64 aGuardTimer, const TDesC& aMatchString)
+ {
+ CScript * self = new(ELeave) CScript;
+ CleanupStack::PushL(self);
+ self->ConstructL(aTestUtils, aLog, aGuardTimer, aMatchString);
+ CleanupStack::Pop();
+ return self;
+ }
+
+/**
+ *
+ * CScript static constructor for a script processor which
+ * does not inherit a parser.
+ *
+ * @param "CTestUtils* aTestUtils"
+ * The TestUtils object to use
+ *
+ * @param "CLog* aLog"
+ * The logger to use
+ *
+ * @xxxx
+ *
+ */
+CScript* CScript::NewLC(CTestUtils* aTestUtils, CLog * aLog, TInt64 aGuardTimer, const TDesC& aMatchString)
+ {
+ CScript * self = new(ELeave) CScript;
+ CleanupStack::PushL(self);
+ self->ConstructL(aTestUtils, aLog, aGuardTimer, aMatchString);
+ return self;
+ }
+
+/**
+ *
+ * CScript second-phase constructor, for a script processor which
+ * inherits a parser.
+ *
+ * @param "CParseLine* aParse"
+ * The parser to use
+ *
+ * @param "CTestUtils*"
+ * Dummy parameter (would be used for constructing a parser);
+ * retained to maintain overload distinction
+ *
+ * @param "CLog * aLog"
+ * The logger to use
+ *
+ * @xxxx
+ *
+ */
+void CScript::ConstructL(CParseLine* aParse, CTestUtils*, CLog* aLog, TInt64 aGuardTimer, const TDesC& aMatchString)
+ {
+ iLog = aLog;
+ iGuardTimer = aGuardTimer;
+
+ iMatchString = aMatchString.AllocL(); // should be the same as that for aParse, for moment don't check
+
+ iParse = aParse;
+ iParseOwner = EFalse;
+
+ iPauseAtEnd = EFalse;
+
+#if !defined (__TSU_TESTFRAMEWORK__)
+ iScriptDepth++;
+#endif
+
+ }
+
+/**
+ *
+ * CScript static constructor for a script processor which
+ * inherits a parser.
+ *
+ * @param "CParseLine* aParse"
+ * The parser to use
+ *
+ * @param "CTestUtils* aTestUtils"
+ * The TestUtils object to use
+ *
+ * @param "CLog* aLog"
+ * The logger to use
+ *
+ * @xxxx
+ *
+ */
+CScript* CScript::NewL(CParseLine* aParse, CTestUtils* aTestUtils, CLog* aLog, TInt64 aGuardTimer, const TDesC& aMatchString)
+ {
+ CScript* self = new(ELeave) CScript;
+ CleanupStack::PushL(self);
+ self->ConstructL(aParse, aTestUtils, aLog, aGuardTimer, aMatchString);
+ CleanupStack::Pop();
+ return self;
+ }
+
+/**
+ *
+ * CScript static constructor for a script processor which
+ * inherits a parser.
+ *
+ * @param "CParseLine* aParse"
+ * The parser to use
+ *
+ * @param "CTestUtils* aTestUtils"
+ * The TestUtils object to use
+ *
+ * @param "CLog* aLog"
+ * The logger to use
+ *
+ * @xxxx
+ *
+ */
+CScript* CScript::NewLC(CParseLine* aParse, CTestUtils* aTestUtils, CLog* aLog, TInt64 aGuardTimer, const TDesC& aMatchString)
+ {
+ CScript* self = new(ELeave) CScript;
+ CleanupStack::PushL(self);
+ self->ConstructL(aParse, aTestUtils, aLog, aGuardTimer, aMatchString);
+ return self;
+ }
+
+/**
+ *
+ * CScript destructor
+ *
+ * @xxxx
+ *
+ */
+CScript::~CScript()
+ {
+ // delete parser if we own it
+ if(iParseOwner)
+ {
+ delete iParse;
+ iParse = NULL;
+ }
+
+ // delete scriptbuffer
+ delete iScriptBuffer;
+
+ delete iMatchString;
+
+#if !defined (__TSU_TESTFRAMEWORK__)
+ iScriptDepth--;
+#endif
+ }
+
+
+/**
+ *
+ * Open and read a script file.
+ *
+ * @param "TFileName aScriptFileName"
+ * The script file name
+ *
+ * @return "TBool"
+ * true if script file successfully read
+ *
+ * @xxxx
+ *
+ */
+#ifdef EXCLUDE_FOR_UNITTEST
+TBool CScript::OpenScriptFile(CFileName* /*aScriptFileName*/)
+ {
+ // empty function to silence OPT:REF warning under WINS UREL build
+ return ETrue;
+ }
+#else
+TBool CScript::OpenScriptFile(CFileName* aScriptFileName)
+ {
+ // get the full pathname default drive name and extension
+ _LIT(KRelated,"\\xx.script");
+ TParse parseScriptFileName;
+ TInt returnCode = parseScriptFileName.Set(aScriptFileName->FileName(), &KRelated, NULL);
+ if (returnCode != KErrNone)
+ {
+ ERR_PRINTF2(_L("Could not set script filename: %S"), &parseScriptFileName.FullName());
+ Pause();
+ return EFalse;
+ }
+
+#if !defined (__TSU_TESTFRAMEWORK__)
+ if (iScriptDepth > KMaxDepthRecursion)
+ {
+ // prevent the parser from recursing forever
+ ERR_PRINTF2(_L("Script parser aborting: depth:%d"), iScriptDepth);
+ return EFalse;
+ }
+#if !defined(__WINS__)
+ if (iScriptDepth > 3)
+ {
+ // on target, we are likely to KERN-EXEC 3 if nesting more than 4 levels
+ WARN_PRINTF2(_L("Warning : script parser depth = %d"), iScriptDepth);
+ }
+#endif
+#endif
+
+ // connect to the fileserver
+ returnCode = iTheFs.Connect();
+ if (returnCode != KErrNone)
+ {
+ ERR_PRINTF1(_L("Error trying to connect to the file server") );
+ return EFalse;
+ }
+
+
+ RFile listfile;
+ // have we got a drive letter specified - if not, check all drives
+ if (parseScriptFileName.DrivePresent())
+ {
+ returnCode = listfile.Open(iTheFs, parseScriptFileName.FullName(), EFileRead | EFileShareAny);
+ }
+ else
+ {
+ // checks C, D, E and Z drives - this is ugly, is there a better way of doing this?
+ INFO_PRINTF1(_L("Looking for script file on all drives..."));
+ _LIT(KDriveC, "C:");
+ parseScriptFileName.Set(aScriptFileName->FileName(), &KRelated, &KDriveC);
+ returnCode = listfile.Open(iTheFs, parseScriptFileName.FullName(), EFileRead | EFileShareAny);
+ if (returnCode != KErrNone)
+ {
+ _LIT(KDriveD, "D:");
+ parseScriptFileName.Set(aScriptFileName->FileName(), &KRelated, &KDriveD);
+ returnCode = listfile.Open(iTheFs, parseScriptFileName.FullName(), EFileRead | EFileShareAny);
+ if (returnCode != KErrNone)
+ {
+ _LIT(KDriveE, "E:");
+ parseScriptFileName.Set(aScriptFileName->FileName(), &KRelated, &KDriveE);
+ returnCode = listfile.Open(iTheFs, parseScriptFileName.FullName(), EFileRead | EFileShareAny);
+ if (returnCode != KErrNone)
+ {
+ _LIT(KDriveZ, "Z:");
+ parseScriptFileName.Set(aScriptFileName->FileName(), &KRelated, &KDriveZ);
+ returnCode = listfile.Open(iTheFs, parseScriptFileName.FullName(), EFileRead | EFileShareAny);
+ }
+ }
+ }
+ }
+
+ // check if open fails
+ if (returnCode != KErrNone)
+ {
+ parseScriptFileName.Set(aScriptFileName->FileName(), &KRelated, NULL);
+ ERR_PRINTF2(_L("Failed to open script file : %S"), &parseScriptFileName.FullName());
+ listfile.Close();
+ iTheFs.Close();
+ Pause();
+ return EFalse;
+ }
+
+ // display the file being processed
+ INFO_PRINTF2(_L("Reading script %S"), &parseScriptFileName.FullName());
+
+ // get the script file size
+ TInt listfilesize;
+ returnCode = listfile.Size(listfilesize);
+ if (returnCode != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to read script file: %S size "), &parseScriptFileName.FullName());
+ listfile.Close();
+ iTheFs.Close();
+ return EFalse;
+ }
+
+ // JW 30-10-02 DEF004555
+ // Buffer was being orphaned if already allocated, where there was more than one
+ // script file on the command line
+ // Now, we check for this and delete iScriptBuffer if it already exists
+ if(iScriptBuffer)
+ {
+ delete iScriptBuffer;
+ iScriptBuffer = NULL;
+ }
+
+ // get a buffer to read the file into
+ TRAPD(err, iScriptBuffer = HBufC8::NewL(listfilesize));
+ if (err != KErrNone || iScriptBuffer == NULL)
+ {
+ ERR_PRINTF2(_L("Failed to allocate memory for script file %S "), &parseScriptFileName.FullName());
+ listfile.Close();
+ iTheFs.Close();
+ return EFalse;
+ }
+
+ // get a pointer to the buffer
+ TPtr8 ptr = iScriptBuffer->Des();
+
+ // read the file into the buffer
+ returnCode = listfile.Read(ptr);
+ if (returnCode != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to read script file %S "), &parseScriptFileName.FullName());
+ listfile.Close();
+ iTheFs.Close();
+ return EFalse;
+ }
+
+ listfile.Close();
+ iTheFs.Close();
+ return ETrue;
+ }
+#endif // EXCLUDE_FOR_UNITTEST
+
+/**
+ *
+ * Parse and execute script file.
+ * Assumes script file has been read into iScriptBuffer
+ *
+ * @return "TVerdict"
+ * The script verdict (for logging)
+ *
+ * @xxxx
+ *
+ */
+TVerdict CScript::ExecuteScriptL()
+ {
+ // use TLex to decode the script
+ TLex8 llex(*iScriptBuffer);
+
+ // keep a count of the line number
+ TInt8 lineNo = 1;
+
+ // loop though processing the rest a line at a time
+ while(!llex.Eos())
+ {
+ // skip any spaces
+ while ( llex.Peek() == ' ' )
+ llex.Inc();
+
+ // mark the start of the line
+ llex.Mark();
+
+ // move to the next
+ while(!llex.Eos() && llex.Peek() != '\n')
+ llex.Inc();
+
+ // step over \n
+ if ( llex.Peek() == '\n' )
+ llex.Inc();
+
+ // get the line
+ TPtrC8 pline = llex.MarkedToken();
+ if (pline.Length() != 0)
+ {
+ // and then process
+ ProcessLineL(pline, lineNo);
+ }
+
+ // on to the next line
+ lineNo++;
+ }
+
+ // script processing complete, now return the script verdict
+ // Note: the script verdicts are just for the log
+ // if no tests failed then return pass for the script
+ // this covers scripts which do not test anything
+ return (iFail == 0 ? EPass : EFail );
+ }
+
+/**
+ *
+ * Process a single line from the script file.
+ *
+ * @param "const TDesC8& aNarrowline"
+ * The script line
+ *
+ * @param "TInt8 lineNo"
+ * The script line number
+ *
+ * @xxxx
+ *
+ */
+void CScript::ProcessLineL(const TDesC8& aNarrowline, TInt8 aLineNo)
+ {
+ // call parse to process line
+ iParse->ProcessLineL(aNarrowline, aLineNo);
+ }
+
+/**
+ *
+ * Display the accumulated script results.
+ *
+ * @xxxx
+ *
+ */
+void CScript::DisplayResults()
+ {
+
+ INFO_PRINTF1(_L("Test Results Summary ") );
+ INFO_PRINTF1(_L("-------------------- ") );
+ INFO_PRINTF2(_L("Passed :%d"), iPass);
+ INFO_PRINTF2(_L("Failed :%d"), iFail);
+ INFO_PRINTF2(_L("Inconclusive :%d"), iInconclusive);
+ INFO_PRINTF2(_L("Test suite errors :%d"), iTestSuiteError);
+ INFO_PRINTF2(_L("Aborted :%d"), iAbort);
+ INFO_PRINTF2(_L("KnownFailure :%d"), iKnownFailure); //A new TVerdict
+ INFO_PRINTF2(_L("Total :%d"), iTotal);
+
+ if(iPauseAtEnd)
+ {
+ // A pause at the end has been requested
+ Pause();
+ }
+
+ }
+
+/**
+ *
+ * Pause testing.
+ * NOTE : stubbed pending re-implementation of user input
+ *
+ * @xxxx
+ *
+ */
+void CScript::Pause()
+ {
+ WARN_PRINTF1(_L("Warning : PAUSE not implemented"));
+ }
+
+/**
+ *
+ * Display error on the console and invite abort.
+ * NOTE : stubbed pending re-implementation of user input
+ *
+ * @xxxx
+ *
+ */
+TBool CScript::BreakOnError()
+ {
+ WARN_PRINTF1(_L("Warning : BREAK_ON_ERROR not implemented"));
+ return EFalse;
+ }
+
+/**
+ *
+ * Add a test result to the accumulated totals.
+ *
+ * @param "TVerdict aTestVerdict"
+ * The test verdict
+ *
+ * @xxxx
+ *
+ */
+void CScript::AddResult(TVerdict aTestVerdict)
+ {
+ // another test complete, so increment total
+ iTotal++;
+
+ // add in the current result
+ switch (aTestVerdict)
+ {
+ case EPass:
+ iPass++;
+ break;
+ case EFail:
+ iFail++;
+ break;
+ case EInconclusive:
+ iInconclusive++;
+ break;
+ case ETestSuiteError:
+ iTestSuiteError++;
+ break;
+ case EAbort:
+ iAbort++;
+ break;
+ case EKnownFailure: //A new TVerdict for a known failed test
+ iKnownFailure++;
+ break;
+ }
+
+ // display the result
+ TPtrC verdictText = CLog::TestResultText(aTestVerdict);
+ TPtrC currentSuiteName = iParse->CurrentSuiteName();
+ TPtrC currentStepName = iParse->CurrentStepName();
+
+ iLog->LogResult(aTestVerdict, _L("Test Result for %S:%S is %S "),
+ ¤tSuiteName, ¤tStepName, &verdictText);
+
+ }
+
+/**
+ *
+ * Add a test result from a subscript to the accumulated totals.
+ *
+ * @param "CScript* aSubScript"
+ * The subscript
+ *
+ * @xxxx
+ *
+ */
+void CScript::AddResult(CScript* aSubScript)
+ {
+
+ iPass += aSubScript->iPass;
+ iFail += aSubScript->iFail;
+ iInconclusive += aSubScript->iInconclusive;
+ iTestSuiteError += aSubScript->iTestSuiteError;
+ iAbort += aSubScript->iAbort;
+ iKnownFailure += aSubScript->iKnownFailure;
+ iTotal +=aSubScript->iTotal;
+ }
+
+/**
+ *
+ * Traceable logging function for parseline.
+ *
+ * @param "const TText8* aFile"
+ * Source code file name
+ *
+ * @param "TInt aLine"
+ * Source code line
+ *
+ * @param "TInt aSeverity"
+ * Severity level required to log
+ *
+ * @param "TRefByValue<const TDesC16> aFmt"
+ * Printf-style format.
+ *
+ * @param "..."
+ * Variable print parameters
+ *
+ * @xxxx
+ *
+ */
+void CScript::LogExtra(const TText8* aFile, TInt aLine, TInt aSeverity,
+ TRefByValue<const TDesC16> aFmt,...)
+ {
+ VA_LIST aList;
+ VA_START(aList, aFmt);
+
+ if(aSeverity)
+ {
+ if(iLog)
+ {
+ iLog->LogExtra(aFile, aLine, aSeverity, aFmt, aList);
+ }
+ }
+
+ VA_END(aList);
+ }