diff -r 417699dc19c9 -r c7e9f1c97567 xml/legacyminidomparser/xmlparser/test/t_smiltranslatortest.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml/legacyminidomparser/xmlparser/test/t_smiltranslatortest.cpp Mon Sep 13 13:16:40 2010 +0530 @@ -0,0 +1,1219 @@ +// Copyright (c) 2003-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 file contains the Console Test Harness for testing the SMILTranslator .dll +// It carries this out by searching for all files of a certain type (as specified by +// KWildName) that reside in a given set of directories (as specified by KInputPathList) +// It then passes each file through a Parser object, picks up the resultant Document +// object and passes this straight back to the composer object. Output is a new XML +// file of the same name but different directory (same as initial directory but with +// KTestFindStr replaced by KTestReplaceStr & KTestReplaceStr2) - these directories are +// created automatically. The application then reports any errors for each file before +// moving onto the next one. These error reports are copied to the console screen (but +// usually too fast to read); to the output window in developer studio; and to a flat +// file (named and located as specified in KErrorFileName) +// There are 3 types of test that may be run. The Basic test merely +// translates all input files to output files. The Performance test does the same thing +// multiple times (as specified by KPerformanceTestIterations), although the log file +// output will only relate to the last run. Finally the Memory test utilises the Heap +// Allocation Failure tool to incrementally run and progressively fail at each and every +// attempt to allocate memory, it's finally run should complete successfully to prove +// that no memory leaks have occurred in spite of X hundreds of previously failed runs. +// Note that this finally test should be done with a much reduced number of files +// residing in the input directories. +// The application can test ASCII or Unicode input and output (4 combinations possible). +// To vary the input you must manually add ASCII or Unicode files to the input +// directories. +// The tests can be run automatically or interactively: +// For interactive tests, run with '-i as follows: +// SMILTRANSLATORTEST.EXE -i +// To run with out user interaction, please see the following examples: +// SMILTRANSLATORTEST.EXE -h # show command line help +// SMILTRANSLATORTEST.EXE # runs with default options +// SMILTRANSLATORTEST.EXE -file_type ascii -data_mode file -test_type basic # same as above +// SMILTRANSLATORTEST.EXE -use_file_handles # msgapi2 only +// SMILTRANSLATORTEST.EXE -use_full_paths # msgapi2 only +// SMILTRANSLATORTEST.EXE -test_type performance -performance_iteratons 3 # performance test with 3 iterations +// +// + +/** + @file +*/ + +//#define DEBUG_SMILTRANSLATORTEST_ + +#include +#include +#include +#include +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "t_smildtdenum.h" +#endif +#include "t_SmilDtd.h" +#include + +// Constants +_LIT(KErrorFileName,"c:\\legacyminidomparsertest\\SMIL_Test_Files\\ErrorLog.txt"); +_LIT(KParseError," Parse File error = "); +_LIT(KComposeError," Compose File error = "); +_LIT(KOutputNewLine,"\r\n"); +_LIT(KStartFile,"Starting test of file "); +_LIT(KTxtAsciiOrUnicode,"Unicode (F1), Ascii (F2) or Utf-8 (F3) output?"); +_LIT(KTxtBufferOrFile,"\nTest file API (F1), test buffer API (F2)"); +_LIT(KTxtChooseTest,"\nPress:\nF1 (or any other key) for Basic test\nF2 for Performance test\nF3 for Memory Allocation test"); +_LIT(KSmilTranslatorTest,"Smil Translator"); +_LIT(KInputPathList, "c:\\legacyminidomparsertest\\SMIL_Test_Files\\SMIL_Input\\Valid\\;c:\\legacyminidomparsertest\\SMIL_Test_Files\\MMS_Input\\Valid\\;c:\\legacyminidomparsertest\\SMIL_Test_Files\\SMIL_Input\\Invalid\\;c:\\legacyminidomparsertest\\SMIL_Test_Files\\MMS_Input\\Invalid\\;"); +_LIT(KTestFindStr, "_Input\\"); +_LIT(KTestReplaceStr, "_Output\\"); +_LIT(KWildName, "*.txt"); // read all file that match *.txt +_LIT(KOptionI, "-i"); // unary: interactive mode +_LIT(KOptionH, "-h"); +// note: traditional style args "--file-type" don't work with the CCommandLineArguments class +_LIT(KOptionFileType, "-file_type"); // binary: ascii, utf8, unicode +_LIT(KOptionDataMode, "-data_mode"); // binary: buffer, file +_LIT(KOptionTestType, "-test_type"); // binary: basic, performance, memory +_LIT(KOptionPerformanceIterations, "-performance_iterations"); // binary: +_LIT(KOptionUseFileHandles, "-use_file_handles"); // unary: use file handles as input +_LIT(KOptionUseFullPaths, "-use_full_paths"); // unary: use full paths as input +_LIT(KTxtChooseFileInput, "Choose input file type: Using file path (F1), Using file handle (F2)?"); + +// Globals +LOCAL_D CTrapCleanup* theCleanup; +LOCAL_D CActiveScheduler* scheduler; +LOCAL_D RTest test(KSmilTranslatorTest); +LOCAL_D RFs fileSystem; +class CTestConfig; +LOCAL_D CTestConfig* testConfig; + +// +// TestConfig +class CTestConfig : public CBase + { +public: + typedef enum {EBasic, EPerformance, EMemory} TTestType; + typedef enum {EFileData, EBufferData} TXMLDataMode; + static CTestConfig* NewLC(); + ~CTestConfig() {} + + TInt ProcessCommandLineL(); + void InteractiveMode(); + + // accessors + TBool NeedsHelp() const {return iNeedsHelp; } + TBool IsInteractive() const {return iIsInteractive; } + TXMLFileType FileType() const {return iFileType; } + TXMLDataMode DataMode() const {return iDataMode; } + TTestType TestType() const {return iTestType; } + TInt PerformanceTestIterations() const {return iPerformanceTestIterations; } + + // display + void DisplayHelp(); + void UseageErr(); + void Dump(); + + TBool UseFileHandles() const {return iUseFileHandles; } + + +private: + void ConstructL(); + TBool UnaryArgPresent(CCommandLineArguments* aArgs,TInt aArgCount, const TDesC& aOption); + TInt ExtractBinaryArg(CCommandLineArguments* aArgs,TInt aArgCount, const TDesC& aOption,TBuf<32>& aBuf); + + TBool FileTypeFromStr(const TBuf<32>& aFileType); + TBool DataModeFromStr(const TBuf<32>& aDataMode); + TBool TestTypeFromStr(const TBuf<32>& aTestType); +private: + TBool iNeedsHelp; + TBool iIsInteractive; + TXMLFileType iFileType; + TTestType iTestType; + TXMLDataMode iDataMode; + TInt iPerformanceTestIterations; + TBool iUseFileHandles; + }; + +void CTestConfig::ConstructL() + { + iNeedsHelp=EFalse; + iIsInteractive=EFalse; + iFileType=EAscii; + iTestType=EBasic; + iDataMode=EFileData; + iPerformanceTestIterations=100; + iUseFileHandles = EFalse; + } + +CTestConfig* CTestConfig::NewLC() + { + CTestConfig* self=new(ELeave)CTestConfig(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +TBool CTestConfig::FileTypeFromStr(const TBuf<32>& aFileType) + { + TBool found=ETrue; + if(aFileType.Compare(_L("ascii"))==0) + { + iFileType=EAscii; + } + else if(aFileType.Compare(_L("utf8"))==0) + { + iFileType=EUtf8; + } + else if (aFileType.Compare(_L("unicode"))==0) + { + iFileType=EUnicode; + } + else + { + found=EFalse; + } + return found; + } + +TBool CTestConfig::DataModeFromStr(const TBuf<32>& aDataMode) + { + TBool found=ETrue; + if(aDataMode.Compare(_L("buffer"))==0) + { + iDataMode=EBufferData; + } + else if(aDataMode.Compare(_L("file"))==0) + { + iDataMode=EFileData; + } + else + { + found=EFalse; + } + return found; + } + +TBool CTestConfig::TestTypeFromStr(const TBuf<32>& aTestType) + { + TBool found=ETrue; + if (aTestType.Compare(_L("basic"))==0) + { + iTestType=EBasic; + } + else if (aTestType.Compare(_L("performance"))==0) + { + iTestType=EPerformance; + } + else if (aTestType.Compare(_L("memory"))==0) + { + iTestType=EMemory; + } + else + { + found=EFalse; + } + return found; + } + +void CTestConfig::DisplayHelp() + { + test.Printf(KOptionH); + test.Printf(_L("\thelp\r\n")); + test.Printf(KOptionI); + test.Printf(_L("\tinteractive mode\r\n")); + test.Printf(KOptionFileType); + test.Printf(_L("\tascii|utf8|unicode\r\n")); + test.Printf(KOptionDataMode); + test.Printf(_L("\tbuffer-data|file-data\r\n")); + test.Printf(KOptionTestType); + test.Printf(_L("\tbasic|performance|memory\r\n")); + test.Printf(KOptionPerformanceIterations); + test.Printf(_L(" N\tthe number of iterations to perform\r\n")); + test.Printf(KOptionUseFileHandles); + test.Printf(_L("\tuse file handles for the test\r\n")); + test.Printf(KOptionUseFullPaths); + test.Printf(_L("\tuse file paths for the test\r\n")); + } + +void CTestConfig::UseageErr() + { + test.Printf(_L("\r\nUseage Err:\r\n")); + DisplayHelp(); + } + +void CTestConfig::Dump() + { + RDebug::Print(_L("\r\n")); + RDebug::Print(_L("SMILTRANSLATORTEST Config Settings:\r\n")); + RDebug::Print(_L("===================================\r\n")); + RDebug::Print(_L("iNeedsHelp = %d\r\n"),iNeedsHelp); + RDebug::Print(_L("iIsInteractive = %d\r\n"),iIsInteractive); + RDebug::Print(_L("iFiletype = %d\r\n"),iFileType); + RDebug::Print(_L("iTestType = %d\r\n"),iTestType); + RDebug::Print(_L("iDataMode = %d\r\n"),iDataMode); + RDebug::Print(_L("iPerformanceTestIterations = %d\r\n"),iPerformanceTestIterations); + RDebug::Print(_L("iUseFileHanldes = %d\r\n"),iUseFileHandles); + } + +TBool CTestConfig::UnaryArgPresent(CCommandLineArguments *aArgs, TInt aArgCount, const TDesC& aOption) + { + TInt i = 1; + while ((iArg(i).Compare(aOption)) + { + ++i; + } + return i& aBuf) + { + TInt err=KErrNotFound; + TInt i=0; + + while ((iArg(i).Compare(aOption)) + { + ++i; + } + if (iArg(i); + } + else + { + err=KErrArgument; + } + } + return err; + } + +void CTestConfig::InteractiveMode() + { + TKeyCode choice; + + test.Printf(KTxtAsciiOrUnicode); + choice=test.Getch(); + + if(choice==EKeyHelp) + { + iFileType=EAscii; + } + else if(choice==EKeyDial) + { + iFileType=EUtf8; + } + else + { + iFileType=EUnicode; + } + test.Printf(KTxtBufferOrFile); + choice=test.Getch(); + if(choice==EKeyHelp) + { + iDataMode=EBufferData; + } + else + { + iDataMode=EFileData; + } + + // Get user's input on whether to use file paths or file handles for the input files + test.Printf(KOutputNewLine()); + test.Printf(KTxtChooseFileInput()); + choice=test.Getch(); + iUseFileHandles=EFalse; + if(choice==EKeyHelp) // F2 + { + iUseFileHandles = ETrue; + } + + test.Printf(KTxtChooseTest); + choice=test.Getch(); + if(choice==EKeyHelp) // F2 + { + iTestType=EPerformance; + } + else if (choice==EKeyDial) // F3 + { + iTestType=EMemory; + } + else // any key + { + iTestType=EBasic; + } + } + +TInt CTestConfig::ProcessCommandLineL() + { + // Handle command line arguments + CCommandLineArguments* args=CCommandLineArguments::NewLC(); + + TInt argCount=args->Count(); + + // Search for: "-h"/help parameter + if (UnaryArgPresent(args,argCount,KOptionH)) + { + iNeedsHelp = ETrue; + CleanupStack::Pop(args); + delete args; + return KErrNone; + } + + // Search for: "-i"/interactive parameter + if(UnaryArgPresent(args,argCount,KOptionI)) + { + if (argCount==2) + { + iIsInteractive=ETrue; + } + else + { + UseageErr(); + } + } + // Search for: "-usefilehandles" parameter + if(UnaryArgPresent(args,argCount,KOptionUseFileHandles)) + { + iUseFileHandles=ETrue; + } + // Search for: "-usefullpaths" parameter + if(UnaryArgPresent(args,argCount,KOptionUseFullPaths)) + { + iUseFileHandles=EFalse; + } + + // Search for: --file-type, --data-mode, --test-type + TBuf<32> buf; + TInt err; + if (((err=ExtractBinaryArg(args,argCount,KOptionFileType,buf))==KErrNone)&&(!FileTypeFromStr(buf))|| + err==KErrArgument) + { + UseageErr(); + CleanupStack::PopAndDestroy(args); + return KErrArgument; + } + if (((err=ExtractBinaryArg(args,argCount,KOptionDataMode,buf))==KErrNone)&&(!DataModeFromStr(buf))|| + err==KErrArgument) + { + UseageErr(); + CleanupStack::PopAndDestroy(args); + return KErrArgument; + } + if (((err=ExtractBinaryArg(args,argCount,KOptionTestType,buf))==KErrNone)&&(!TestTypeFromStr(buf))|| + err==KErrArgument) + { + UseageErr(); + CleanupStack::PopAndDestroy(args); + return KErrArgument; + } + if (((err=ExtractBinaryArg(args,argCount,KOptionPerformanceIterations,buf))==KErrNone)) + { + TLex16 lexer(buf.Ptr()); + TInt iterations; + lexer.Val(iterations); + iPerformanceTestIterations = iterations; + } + else if (err==KErrArgument) + { + UseageErr(); + CleanupStack::PopAndDestroy(args); + return KErrArgument; + } + CleanupStack::PopAndDestroy(args); + return KErrNone; + } + +// + +class CTestDataSupplier : public CBase, public MMDXMLParserDataProvider + { +public: + static CTestDataSupplier* NewL(RFs &aRFs, const TDesC& aFileName); + ~CTestDataSupplier(); + + // From MMDXMLParserDataProvided + void GetData(TPtrC8 &aPtr, TRequestStatus &aStatus); + void Disconnect(); + +private: + void ConstructL(RFs &aRFs, const TDesC& aFileName); + +private: + HBufC8* iCurrentChunk; + RFile iFile; + TInt iChunkSize; // Start at 1, then increment for subsequent chunk + }; + + +CTestDataSupplier* CTestDataSupplier::NewL(RFs &aRFs, const TDesC& aFileName) + { + CTestDataSupplier* self = new (ELeave) CTestDataSupplier(); + CleanupStack::PushL(self); + self->ConstructL(aRFs, aFileName); + CleanupStack::Pop(self); + return self; + } + +CTestDataSupplier::~CTestDataSupplier() + { + iFile.Close(); + delete iCurrentChunk; + } + +// From MMDXMLParserDataProvided +// TODO: Should GetData be a leaving function? Allows more flexibility to implementations of this funtion? +void CTestDataSupplier::GetData(TPtrC8 &aPtr, TRequestStatus &aStatus) + { + // Read the data into the descriptor + delete iCurrentChunk; + iCurrentChunk = NULL; + iCurrentChunk = HBufC8::NewL(iChunkSize); + TPtr8 chunk = iCurrentChunk->Des(); + iFile.Read(chunk, iChunkSize); // Ignore the error code, assume end of file if we haven't read any data. + + TDataProviderResults result; + + if (iCurrentChunk->Length() != 0) + { + aPtr.Set(*iCurrentChunk); + result = KMoreData; + } + else + { + // Assume that if we haven't got any data then we're at the end of the stream. + result = KDataStreamEnd; + } + +// iChunkSize++; + TRequestStatus *s = &aStatus; + User::RequestComplete(s, (TInt)result); + return; + } + +void CTestDataSupplier::Disconnect() + { + // Don't need to do anything here. + } + +void CTestDataSupplier::ConstructL(RFs &aRFs, const TDesC& aFileName) + { + iChunkSize = 1; + + // Open the file that will supply the data + User::LeaveIfError(iFile.Open(aRFs, aFileName, EFileRead)); + } + + +// +// CSmilTranslatorTestUtils declaration +// + +class CSmilTranslatorTestUtils : public CActive, public MMDXMLParserObserver, public MMDXMLComposerObserver + { +public: + static CSmilTranslatorTestUtils* NewLC(); + ~CSmilTranslatorTestUtils(); + void ConstructL(); + void RunTestL(); + TInt FilesProcessed() const {return iFilesProcessed; } + +public: // from CActive + void DoCancel(); + void RunL(); + +public: // from MMDXMLParserObserver + void ParseFileCompleteL(); + +public: // from MMDXMLComposerObserver + void ComposeFileCompleteL(); + +private: + CSmilTranslatorTestUtils(); + void SetOutputFileName(); + void AppendErrorStr(TInt aError, TDes& aOutputMsg); + void AppendSeverityStr(TInt aSeverity, TDes& aOutputMsg); + +private: + enum TComposerState + { + EComposing, + ESizing + }; + + RFs iSession; + CMDXMLDocument* iXMLDoc; + + + CMDXMLParser* iParser; + CMDXMLComposer* iComposer; + TBuf<255> iInputFileName; + TBuf<255> iOutputFileName; + TComposerState iComposerState; + TInt iSize; + RFile iErrorFile; + CTestDataSupplier* iDataSupplier; + + // return list of found files used by TFileFinder class + CDir* iFileList; + + // buffer for composing the error messages for output to the screen and error file + TBuf<255> iOutputMsg; + + TFindFile *iFileFinder; + + TInt iState; + TInt iErr; + TInt iIndex; + + enum TSmilTestStates + { + KInit = 0x00, + KParseFile, + KCheckResults, + KEnd + }; + + TTime iStartTime; + TTime iStartComposeTime; + TInt64 iComposeTime; + TInt iFilesProcessed; + + TBool iUseFileHandle; + }; + +//=================================================================================== + +// +// CSmilTranslatorTestUtils definition +// + +CSmilTranslatorTestUtils* CSmilTranslatorTestUtils::NewLC() + { + CSmilTranslatorTestUtils* self = new (ELeave) CSmilTranslatorTestUtils(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +//=================================================================================== + +CSmilTranslatorTestUtils::~CSmilTranslatorTestUtils() + { + delete iFileList; + delete iXMLDoc; + delete iParser; + delete iComposer; + iSession.Close(); + } + +//=================================================================================== + +CSmilTranslatorTestUtils::CSmilTranslatorTestUtils() : CActive(EPriorityStandard), iFileFinder() + { + } + +//=================================================================================== + +void CSmilTranslatorTestUtils::ConstructL() + { + + iSession.Connect(); + iComposer = CMDXMLComposer::NewL(this); +#define VALIDATE +#ifndef VALIDATE + iParser = CMDXMLParser::NewL(this); +#else + CSMILDtd* smil = CSMILDtd::NewLC(); + iParser = CMDXMLParser::NewL(this, smil); + CleanupStack::Pop(smil); +#endif + + iUseFileHandle = testConfig->UseFileHandles(); + + iState = KInit; + iErr = KErrNone; + iStartTime.UniversalTime(); + iFilesProcessed = 0; + + CActiveScheduler::Add(this); + + TRequestStatus *s = &iStatus; + User::RequestComplete(s, KErrNone); + SetActive(); + } + +//=================================================================================== + +void CSmilTranslatorTestUtils::RunL() + { + RunTestL(); + } + +//=================================================================================== + +void CSmilTranslatorTestUtils::DoCancel() + { + } + +//=================================================================================== + +#define DES_AS_8_BIT(str) (TPtrC8((TText8*)((str).Ptr()), (str).Size())) + +void CSmilTranslatorTestUtils::RunTestL() + { + TRequestStatus *s = &iStatus; + + // used to generate a leave if an out of memory error was encountered, specifically + // during the memory test loop in E32Main(). This is necessary because leaves in + // the .dll Active Object RunL() functions do not return to this application, so + // have to be Trapped in the Active objects and translated into an error code. + TBool memoryError = EFalse; + + switch(iState) + { + case KInit: + { + // Utility class for file manipulation + iFileFinder = new TFindFile(iSession); + + TPtrC errorFileName(KErrorFileName); + + // create err dir if doesn't exist - this api ignores the file name (ignores everything after final '/') + fileSystem.MkDirAll(KErrorFileName); + + // overwrite any existing file of this name + iErr = iErrorFile.Replace(iSession, errorFileName, EFileWrite | EFileStreamText); + + if(iErr == KErrNone) + { + TBuf<1> bom; + bom.Append(CEditableText::EByteOrderMark); + iErrorFile.Write(DES_AS_8_BIT(bom)); + // will search multiple directories, but halt after completing current directory + // if at least one match is made. Remembers which directories have been searched + // in order to continue search using .FindWild() function later + iErr = iFileFinder->FindWildByPath(KWildName, &KInputPathList, iFileList); + iIndex = 0; + } + + if(iErr == KErrNone) + { + iState = KParseFile; + } + else + { + iState = KEnd; + } + User::RequestComplete(s, KErrNone); + SetActive(); + } + break; + + case KParseFile: + { + ++iFilesProcessed; + iErr = KErrNone; + + TParse fullEntry; + fullEntry.Set((*iFileList)[iIndex++].iName,& iFileFinder->File(),NULL); + iInputFileName = fullEntry.FullName(); // extract individual path + name from list + SetOutputFileName(); // output name is based on input one + + iOutputMsg = KStartFile; + iOutputMsg.Append(iInputFileName); // display full path + test.Start(iOutputMsg); // print to console + + // test console automatically places output on a new line, for output + // to error file we need to add white space ready for next line + iOutputMsg.Append(KOutputNewLine); + iErrorFile.Write(DES_AS_8_BIT(iOutputMsg)); // print to error file + + // schedule Parser active object for call to it's RunL function + if (testConfig->DataMode() == CTestConfig::EBufferData) + { + // We're testing the buffering API... + // Create a data supplier object and pass it in to the parser + delete iDataSupplier; + iDataSupplier = NULL; + iDataSupplier = CTestDataSupplier::NewL(iSession, iInputFileName); + iParser->ParseSource(iDataSupplier); + } + else + { + if( iUseFileHandle ) + { + RFile file; + User::LeaveIfError(file.Open(iSession, iInputFileName, EFileRead | EFileShareReadersOnly)); + // No function declaration of ParseFile() that take RFile Object parameter + // iParser->ParseFile(file); + iParser->ParseFile(iSession, iInputFileName); + } + else + { + // We're testing the file mode so parse the file. + iParser->ParseFile(iSession, iInputFileName); + } + } + + iState = KCheckResults; + iStatus = KRequestPending; + SetActive(); + } + break; + + case KCheckResults: + { + // when execution begins again one parse followed by a compose would have + // completed for the current file, handle any error messages generated here + iErr = iParser->Error(); + TInt severity = iParser->ErrorSeverity(); + if(iErr != KErrNone) + { + iOutputMsg = KParseError; + AppendErrorStr(iErr, iOutputMsg); + AppendSeverityStr(severity, iOutputMsg); + iOutputMsg.Append(KOutputNewLine); + + // IF there are no more errors for this file bung in an + // extra line to make output more prominent + if(iComposer->Error() == KErrNone) + { + iOutputMsg.Append(KOutputNewLine); + } + test.Printf(iOutputMsg); // print to console + iErrorFile.Write(DES_AS_8_BIT(iOutputMsg)); // print to error file + + if(iErr == KErrNoMemory) + { + memoryError = ETrue; + } + } + + iErr = iComposer->Error(); + severity = iComposer->ErrorSeverity(); + if(iErr != KErrNone) + { + iOutputMsg = KComposeError; + AppendErrorStr(iErr, iOutputMsg); + AppendSeverityStr(severity, iOutputMsg); + iOutputMsg.Append(KOutputNewLine); + iOutputMsg.Append(KOutputNewLine); + test.Printf(iOutputMsg); + iErrorFile.Write(DES_AS_8_BIT(iOutputMsg)); + + if(iErr == KErrNoMemory) + { + memoryError = ETrue; + } + } + + test.End(); + + // if the OOM condition occured during Parsing or Composing + if(memoryError) + { + User::Leave(KErrNoMemory); + } + + iState = KParseFile; + + if(iIndex >= iFileList->Count()) + { + // fileList must be deleted after each loop prior to being passed + // back to fileFinder (unnecessary after KErrNotFound) + delete iFileList; + iFileList = 0; // Just in case it doesn't get set in the FindWild + + // continue wildcard search for next directory in list + iErr = iFileFinder->FindWild(iFileList); + iIndex = 0; + if(iErr != KErrNone) + iState = KEnd; + } + + SetActive(); + User::RequestComplete(s, KErrNone); + } + break; + + default: + case KEnd: + { + TTime endTime; + TTimeIntervalSeconds interval; + endTime.UniversalTime(); + endTime.SecondsFrom(iStartTime, interval); + + TBuf<100> time; + _LIT(KComposeTime, "Total time for composing: %d microseconds\n"); + time.Format(KComposeTime, iComposeTime); + iErrorFile.Write(DES_AS_8_BIT(time)); + + _LIT(KTimeTaken, "Total time for tests: %d seconds"); + time.Format(KTimeTaken, interval.Int()); + iErrorFile.Write(DES_AS_8_BIT(time)); + + + delete iFileFinder; + delete iDataSupplier; + CActiveScheduler::Stop(); + } + break; + } + } + +//=================================================================================== + +void CSmilTranslatorTestUtils::AppendErrorStr(TInt aError, TDes& aOutputMsg) + { + switch(aError) + { + case KErrXMLBadAttributeValue: + aOutputMsg.Append(_L("Bad Attribute Value")); break; + + case KErrXMLBadAttributeName: + aOutputMsg.Append(_L("Bad Attribute Name")); break; + + case KErrXMLInvalidChild: + aOutputMsg.Append(_L("Invalid Child")); break; + + case KErrXMLBadNesting: + aOutputMsg.Append(_L("Bad Nesting")); break; + + case KErrXMLIncomplete: + aOutputMsg.Append(_L("Incomplete")); break; + + case KErrXMLBadElementName: + aOutputMsg.Append(_L("Bad Element Name")); break; + + case KErrXMLDuplicateDocTypeTags: + aOutputMsg.Append(_L("Duplicate DocType Tags")); break; + + case KErrXMLDuplicateVersionTags: + aOutputMsg.Append(_L("Duplicate Version Tags")); break; + + case KErrXMLDuplicateRootElements: + aOutputMsg.Append(_L("Duplicate Root Elements")); break; + + case KErrXMLMissingDocTypeTag: + aOutputMsg.Append(_L("Missing DocType Tag")); break; + + case KErrXMLMissingVersionTag: + aOutputMsg.Append(_L("Missing Version Tag")); break; + + case KErrXMLDuplicateAttributeName: + aOutputMsg.Append(_L("Duplicate Attribute Name")); break; + + case KErrXMLMultipleRootElements: + aOutputMsg.Append(_L("Mulitiple Root Elements")); break; + + case KErrXMLCorruptFile: + aOutputMsg.Append(_L("Corrupt File")); break; + + case KErrXMLIllegalCharacter: + aOutputMsg.Append(_L("Illegal Character")); break; + + case KErrXMLBadEntity: + aOutputMsg.Append(_L("Malformed Entity")); break; + + case KErrXMLInvalidElement: + aOutputMsg.Append(_L("Invalid Element")); break; + + case KErrXMLInvalidAttribute: + aOutputMsg.Append(_L("Invalid Attribute")); break; + + case KErrPathNotFound: + aOutputMsg.Append(_L("File Path Not Found")); break; + + case KErrNoMemory: + aOutputMsg.Append(_L("Memory Allocation Failure")); break; + + case KErrNotSupported: + aOutputMsg.Append(_L("Not Supported")); break; + + default: + aOutputMsg.Append(_L("Unknown Error")); break; + } + } + +//=================================================================================== +void CSmilTranslatorTestUtils::AppendSeverityStr(TInt aSeverity, TDes& aOutputMsg) + { + aOutputMsg.Append(_L(", Severity ")); + switch(aSeverity) + { + case EXMLFatal: + aOutputMsg.Append(_L("Fatal")); + break; + case EXMLIndeterminate: + aOutputMsg.Append(_L("Indeterminate")); + break; + case EXMLWorkable: + aOutputMsg.Append(_L("Workable")); + break; + case EXMLNone: + aOutputMsg.Append(_L("None")); + break; + default: + aOutputMsg.Append(_L("Unknown")); + break; + } + } +//=================================================================================== + +void CSmilTranslatorTestUtils::ParseFileCompleteL() +// call back function called from Parser::RunL() + { + // iXMLDoc ends up owned by this class, must delete off the old one on each pass. + delete iXMLDoc; + iXMLDoc = NULL; + + // get parsed file, don't worry about errors, composer should be robust enough to handle bad files + iXMLDoc = iParser->DetachXMLDoc(); + + iComposerState = EComposing; + TRequestStatus *s = &iStatus; + + iStartComposeTime.UniversalTime(); + + // create output dir if doesn't exist - this api ignores the file name (ignores everything after final '/') + fileSystem.MkDirAll(iOutputFileName); + + // schedule composer active object for call to it's RunL function + + if( iUseFileHandle ) + { + RFile file; + TInt fileError = file.Replace(iSession, iOutputFileName, EFileWrite | EFileStream); + + if( fileError==KErrNone ) + { + // No function declaration of ComposeFile() that take RFile Object parameter +// iErr = iComposer->ComposeFile(file, iXMLDoc, filetype); + iErr = iComposer->ComposeFile(iSession, iOutputFileName, iXMLDoc, testConfig->FileType()); + } + else + { + // if a file error has occured, we need to set the internal error state + // and can only do this by trying to compose again with the filepath so + // it fails internally + iErr = iComposer->ComposeFile(iSession, iOutputFileName, iXMLDoc, testConfig->FileType()); + } + } + else + { + iErr = iComposer->ComposeFile(iSession, iOutputFileName, iXMLDoc, testConfig->FileType()); + } + + // we are waiting on this event... + User::RequestComplete(s, KErrNone); + } + +//=================================================================================== + +void CSmilTranslatorTestUtils::ComposeFileCompleteL() +// call back function called from Composer::RunL() + { + TTime timeNow; + timeNow.UniversalTime(); + TTimeIntervalMicroSeconds timeForCompose = timeNow.MicroSecondsFrom(iStartComposeTime); + iComposeTime += timeForCompose.Int64(); + + if (iComposerState == ESizing) + { + // Check the size of the file that has been written against the size calulated by the + // call to CMDXMLComposer::CalculateFileSize + + RFile outputXMLFile; + outputXMLFile.Open(iSession, iOutputFileName, EFileRead); + + TInt actualSize; + User::LeaveIfError(outputXMLFile.Size(actualSize)); + + if (iSize != actualSize) + { + // The calculated file size doesn't match the real file size, this test has failed + TBuf<255> outputMsg; + + outputMsg.Append(KOutputNewLine); + outputMsg.Append(_L("Test Failed - The calculated file size doesn't match the actual size.")); + outputMsg.Append(KOutputNewLine); + + test.Printf(outputMsg); // print to console + iErrorFile.Write(DES_AS_8_BIT(outputMsg)); // print to error file + } + + outputXMLFile.Close(); + + // If we are sizing then stop the active scheduler. Once the scheduler is stopped + // and this function exits, program control resumes where the scheduler was started + // in RunTestL. +// CActiveScheduler::Stop(); + } + + else if (iComposerState == EComposing) + { + // The XML file has been composed. Now we need to run the sizing function to check + // that we can calculate the size correctly. + + // Set the state to sizing and run the sizing operation... + iComposerState = ESizing; + + // Calculate the file size and wait for the callback to this function again. + iComposer->CalculateFileSize(iSize, iXMLDoc, testConfig->FileType()); + } + } + +//=================================================================================== + +void CSmilTranslatorTestUtils::SetOutputFileName() + { + TInt offset; + + iOutputFileName = iInputFileName; + if((offset = iOutputFileName.Find(KTestFindStr)) != KErrNotFound) + { + iOutputFileName.Replace(offset, TPtrC(KTestFindStr).Length(), KTestReplaceStr); + } + } + +//=================================================================================== + +// +// TestHarness implementation +// + + + +LOCAL_C TInt startTestL() + { + TInt err = KErrNone; + + // we may need to make some output dirs if they don't already exist + fileSystem.Connect(); + + scheduler = new (ELeave) CActiveScheduler; + CleanupStack::PushL(scheduler); + CActiveScheduler::Install( scheduler ); + + CSmilTranslatorTestUtils* ttu=CSmilTranslatorTestUtils::NewLC(); + + // suspend execution until active object scheduler is finished + CActiveScheduler::Start(); + + if (ttu->FilesProcessed()==0) + err=KErrNotFound; + + fileSystem.Close(); + CleanupStack::PopAndDestroy(2, scheduler); //scheduler, as well as the object + //placed on the stack by CSmilTranslatorTestUtils::NewLC(); + return err; + } + +LOCAL_C TInt doMainL() + { + testConfig = CTestConfig::NewLC(); + + // set command line options + TInt err=testConfig->ProcessCommandLineL(); + if(err!=KErrNone) + return err; + + // users specified -h: display help to console and abort + if (testConfig->NeedsHelp()) + { + testConfig->DisplayHelp(); + test.Getch(); + return KErrNone; + } + + // user specified -i: let them override settings inside the console + if (testConfig->IsInteractive()) + testConfig->InteractiveMode(); + +#ifdef DEBUG_SMILTRANSLATORTEST_ + testConfig->Dump(); +#endif + + TInt returnCode = KErrNone; + + // performance Performance Test + if (testConfig->TestType() == CTestConfig::EPerformance) + { + TInt loopFor = 0; + do + { + loopFor++; + returnCode=startTestL(); // Qualified: false leavescan error + } + while(loopFor!=testConfig->PerformanceTestIterations() && returnCode == KErrNone); + } + else if (testConfig->TestType()==CTestConfig::EMemory) + { + TInt after = 0; + do + { + after++; + User::__DbgSetAllocFail(RHeap::EUser, RHeap::EDeterministic, after); + returnCode=startTestL(); + } + while(returnCode != KErrNone); + } + // Assume user wants a basic test + else + { + returnCode=startTestL(); + } + + CleanupStack::Pop(testConfig); + return returnCode; + } +void CopyFileL() + { + RFs fs; + fs.Connect(); + CleanupClosePushL(fs); + + CFileMan* fileMan = CFileMan::NewL(fs); + CleanupStack::PushL(fileMan); + + // Do the file copy + //User::LeaveIfError(fileMan->Copy(_L("z:\\gmxmltest.txt"),_L("c:\\gmxmltest.txt"),CFileMan::EOverWrite)); + //User::LeaveIfError(fileMan->Copy(_L("z:\\legacyminidomparsertest"),_L("c:\\legacyminidomparsertest"),CFileMan::EOverWrite|CFileMan::ERecurse)); + + CleanupStack::PopAndDestroy(2); + } + +GLDEF_C TInt E32Main() + { + __UHEAP_MARK; + theCleanup=CTrapCleanup::New(); + test.Start(_L("Smil Translator")); + TRAPD(err,CopyFileL()); + test(err == KErrNone); + TInt returnCode=KErrNone; + TRAP(returnCode,returnCode=doMainL()); + test(returnCode==KErrNone); + delete testConfig; + delete theCleanup; + test.End(); + test.Close(); + __UHEAP_MARKEND; + User::Heap().Check(); + return(KErrNone); + } + +// End Of File