--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgtest/testutils/email/src/ScriptTestUtils.cpp Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,685 @@
+// Copyright (c) 2000-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:
+//
+
+#include "emailtestutils.h"
+#include "scripttestutils.h"
+
+_LIT8(K_IM_CR_LF, "\r\n");
+_LIT(K_IM_LOG_FILE_NAME, "c:\\logs\\email\\imlog%d.txt");
+_LIT(K_IM_END_OF_FILE, "END OF FILE");
+_LIT(K_IM_LOG_TEMP_FILE_NAME, "temp.out");
+_LIT8(K_IM_READ_CANCELLED, "** Read cancelled");
+
+_LIT8(K_IM_TEST_DATE, "Date: ");
+_LIT8(K_IM_TEST_DATE_REPLACEMENT, "date-replacement-string-");
+_LIT8(K_IM_TEST_MESSAGE_ID, "Message-ID: ");
+_LIT8(K_IM_TEST_MESSAGE_ID_REPLACEMENT, "message-id-replacement-string-");
+_LIT8(K_IM_TEST_CONTENT_ID, "Content-ID: ");
+_LIT8(K_IM_TEST_CONTENT_ID_REPLACEMENT, "content-id-replacement-string-");
+_LIT8(K_IM_TEST_BOUNDARY, " boundary=");
+_LIT8(K_IM_TEST_BOUNDARY_REPLACEMENT, "boundary-replacement-string-");
+_LIT8(K_IM_TEST_HELO, "HELO ");
+_LIT8(K_IM_TEST_HELO_REPLACEMENT, "");
+const TInt K_IM_TEST_STRING_MAX = 128;
+const TInt K_IM_TEST_ID_LEN = 5;
+
+
+CScriptTestUtils::CImTestField::~CImTestField()
+ {
+ delete iFieldName;
+ delete iReplacementString;
+ }
+
+CScriptTestUtils::CImFindReplace::~CImFindReplace()
+ {
+ delete iFind;
+ delete iReplace;
+ }
+
+EXPORT_C void CScriptTestUtils::LogToInputFileL(const TDesC& aSourceFileName, const TDesC& aDestFileName, TBool aStandardiseDateFields)
+// Create an email script file from a log file.
+ {
+ StripLogFileL(aSourceFileName, aDestFileName, aStandardiseDateFields, EImLogLineIn);
+ }
+
+EXPORT_C void CScriptTestUtils::LogToOutputFileL(const TDesC& aSourceFileName, const TDesC& aDestFileName, TBool aStandardiseDateFields)
+// Create an email output file from a log file.
+ {
+ StripLogFileL(aSourceFileName, aDestFileName, aStandardiseDateFields, EImLogLineOut);
+ }
+
+CScriptTestUtils::CImFindReplace* CScriptTestUtils::FindVariableDataL(TDes8& aLine)
+// Find any variable data fields in the given line.
+// The field value and its replacement is returned.
+// If the line doesn't contain any variable data then a NULL pointer is returned.
+ {
+ CImFindReplace* replacement = NULL;
+
+ TInt index = iFieldList->Count();
+ HBufC8* fieldName;
+ TPtrC8 startOfLine;
+ TInt lineIndex = 0;
+ while (index--)
+ // Look for each variable field in turn.
+ {
+ fieldName = ((*iFieldList)[index]->iFieldName);
+ lineIndex = fieldName->Des().Size();
+ if (lineIndex <= aLine.Size())
+ {
+ startOfLine.Set(aLine.Left(lineIndex));
+
+ if (fieldName->Des().CompareF(startOfLine) == 0)
+ {
+ TPtrC8 fieldValue;
+ fieldValue.Set(aLine.Mid(lineIndex, aLine.Size() - lineIndex));
+ if (fieldValue.Size() > 1)
+ // Don't include enclosing '<' '>' '"' characters in the value part.
+ {
+ if (((fieldValue[0] == '<') && (fieldValue[fieldValue.Size() - 1] == '>'))
+ || ((fieldValue[0] == '"') && (fieldValue[fieldValue.Size() - 1] == '"'))
+ || ((fieldValue[0] == '[') && (fieldValue[fieldValue.Size() - 1] == ']')))
+ {
+ fieldValue.Set(fieldValue.Mid(1, fieldValue.Size() - 2));
+ }
+ }
+
+ // Set
+ if (fieldValue.Size() > 0)
+ {
+ replacement = new (ELeave) CImFindReplace;
+ replacement->iFind = HBufC8::NewL(fieldValue.Size());
+ *(replacement->iFind) = fieldValue;
+
+ replacement->iReplace = HBufC8::NewL((*iFieldList)[index]->iReplacementString->Des().Size() + K_IM_TEST_ID_LEN);
+ *(replacement->iReplace) = (*iFieldList)[index]->iReplacementString->Des();
+ // Append the ID number to the replacement string.
+ TPtr8 replacementString = replacement->iReplace->Des();
+ TBuf8<K_IM_TEST_ID_LEN> numberString;
+ (*iFieldList)[index]->iNumberFound++;
+ numberString.Num((*iFieldList)[index]->iNumberFound);
+ if ((replacementString.Size() != 0) && (index != 0))
+ replacementString.Append(numberString);
+ }
+ }
+ }
+ }
+
+ return replacement;
+ }
+
+void CScriptTestUtils::ReplaceVariableFields(TDes8& aLine)
+// Replaces any variable data in the given descriptor with a standard equivalent.
+ {
+ TInt index = 0;
+ index = iFindReplaceList->Count();
+ TInt stringPosition;
+ HBufC8* findString;
+ HBufC8* replaceString;
+ while (index--)
+ // Search for each bit of variable data in turn
+ {
+ findString = (*iFindReplaceList)[index]->iFind;
+ replaceString = (*iFindReplaceList)[index]->iReplace;
+ stringPosition = aLine.FindF(findString->Des());
+ if (stringPosition != KErrNotFound)
+ {
+ aLine.Replace(stringPosition, findString->Des().Size(), replaceString->Des());
+ }
+ }
+ }
+
+void CScriptTestUtils::StandardiseVariableFieldsL(const TDesC& aSourceFileName)
+// Write over all the MIME variable field values with standard values.
+ {
+ TInt index = 0;
+ index = iFieldList->Count();
+ while (index--)
+ {
+ (*iFieldList)[index]->iNumberFound = 0;
+ }
+
+ // Open and create the files
+ RFile sourceFile;
+ RFile tempFile;
+ TFileName tempFileName;
+ index = 0;
+ while (aSourceFileName[index] != L'.')
+ {
+ tempFileName.Append(aSourceFileName[index]);
+ index++;
+ }
+ tempFileName.Append(_L(".tmp"));
+
+ TInt err = tempFile.Replace(iTestUtils.FileSession(), tempFileName, EFileShareAny);
+
+ // Open the log file.
+ err = sourceFile.Open(iTestUtils.FileSession(), aSourceFileName, EFileShareReadersOnly);
+ TFileReader fileReader(sourceFile);
+
+ HBufC8* sourceLine = GetLineL(fileReader);
+ CImFindReplace* findReplace;
+ while (0 != sourceLine)
+ // Fill in the find and replace table.
+ {
+ TPtr8 linePtr = sourceLine->Des();
+ CleanupStack::PushL(sourceLine);
+ findReplace = FindVariableDataL(linePtr);
+ if (findReplace)
+ // Add the find and replace strings to the list
+ {
+ iFindReplaceList->AppendL(findReplace);
+ }
+
+ CleanupStack::PopAndDestroy(); // sourceLine
+ sourceLine = GetLineL(fileReader);
+ }
+
+ // Go back to the begining of the source file.
+ fileReader.Seek(0);
+
+ sourceLine = GetLineL(fileReader);
+ // Replace all of the variable field values with the appropriate fixed string.
+ while (0 != sourceLine)
+ {
+ TPtr8 linePtr = sourceLine->Des();
+ CleanupStack::PushL(sourceLine);
+
+ TPtr8 sourceLinePtr = sourceLine->Des();
+ ReplaceVariableFields(sourceLinePtr);
+
+ tempFile.Write(sourceLinePtr);
+ tempFile.Write(K_IM_CR_LF);
+
+ CleanupStack::PopAndDestroy(); // sourceLine
+ sourceLine = GetLineL(fileReader);
+ if (sourceLine)
+ linePtr = sourceLine->Des();
+ }
+
+ // Close the files.
+ sourceFile.Close();
+ tempFile.Close();
+
+ // Delete the source file.
+ err = iTestUtils.FileSession().Delete(aSourceFileName);
+
+ // Rename the temp file as the source file.
+ err = iTestUtils.FileSession().Rename(tempFileName, aSourceFileName);
+ }
+
+
+void CScriptTestUtils::StripLogFileL(const TFileName& aSourceFileName, const TFileName& aDestFileName, TBool aStandardiseDateFields, TImLogLineType aLogLineType)
+ {
+ TBuf8<2> crlf = _L8("\r\n");
+
+ RFile rSourceFile;
+ RFile rOutputFile;
+
+ User::LeaveIfError(rOutputFile.Replace(iTestUtils.FileSession(), aDestFileName, EFileShareAny));
+
+ // Open the log file.
+ User::LeaveIfError(rSourceFile.Open(iTestUtils.FileSession(), aSourceFileName, EFileShareAny));
+
+ TBuf8<2048> scriptLine;
+ TFileReader fileReader(rSourceFile);
+
+ // Copy the incoming data from the log to the script file, removing any formatting.
+ TInt lineCounter = 0;
+ TInt lineIndex;
+ TImLogLineType lastLineType = aLogLineType;
+ TBool waitingForCrLf = EFalse;
+
+ HBufC8* logLine = GetLineL(fileReader);
+ while (logLine != 0)
+ {
+ CleanupStack::PushL(logLine);
+ lineCounter++;
+ lineIndex = 0;
+
+ scriptLine.Zero();
+ TImLogLineType lineType = LineType(logLine);
+ if (EImEmptyLine == lineType)
+ {
+ if (waitingForCrLf)
+ {
+ waitingForCrLf = EFalse;
+ rOutputFile.Write(crlf);
+ }
+ }
+ else if (aLogLineType == lineType)
+ {
+ if ((lastLineType != EImLogLineComment) && (waitingForCrLf))
+ {
+ rOutputFile.Write(crlf);
+ }
+
+ // Copy the line of incoming data to the script file.
+ if (logLine->Size() > 21)
+ {
+ // Copy the logLine from character 20 to the end into the output line.
+ lineIndex = 21;
+ while (lineIndex < logLine->Size())
+ {
+ scriptLine.Append((*logLine)[lineIndex]);
+ lineIndex++;
+ }
+
+ // Write the stripped line to the script file
+ User::LeaveIfError(rOutputFile.Write(scriptLine));
+ }
+
+ waitingForCrLf = ETrue;
+ //
+ }
+ else if (EImLogLineComment == lineType)
+ {}
+ else if (EImReadCancelled == lineType)
+ {
+ if (EImLogLineIn == aLogLineType)
+ {
+ User::LeaveIfError(rOutputFile.Write(K_IM_READ_CANCELLED));
+ rOutputFile.Write(crlf);
+ }
+ }
+ else
+ {
+ // If we're waiting for a crlf then write one regardless of the last line...
+ if (waitingForCrLf)
+ {
+ rOutputFile.Write(crlf);
+ }
+ }
+
+ lastLineType = LineType(logLine);
+
+ CleanupStack::PopAndDestroy(); // logLine
+ logLine = GetLineL(fileReader);
+ }
+
+ if (waitingForCrLf)
+ {
+ rOutputFile.Write(crlf);
+ }
+
+ rSourceFile.Close();
+ rOutputFile.Close();
+
+ if (aStandardiseDateFields)
+ {
+ StandardiseVariableFieldsL(aDestFileName);
+ }
+ }
+
+EXPORT_C CScriptTestUtils* CScriptTestUtils::NewLC(CEmailTestUtils& aTestUtils)
+ {
+ CScriptTestUtils* self = new (ELeave) CScriptTestUtils(aTestUtils);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+void CScriptTestUtils::ConstructL()
+ {
+ iFieldList = new (ELeave) CArrayPtrFlat<CImTestField>(6);
+
+ CImTestField* removeReplaceItem = new (ELeave) CImTestField;
+ removeReplaceItem->iFieldName = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iFieldName) = K_IM_TEST_DATE;
+ removeReplaceItem->iReplacementString = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iReplacementString) = K_IM_TEST_DATE_REPLACEMENT;
+ removeReplaceItem->iNumberFound=0;
+ iFieldList->AppendL(removeReplaceItem);
+
+ removeReplaceItem = new (ELeave) CImTestField;
+ removeReplaceItem->iFieldName = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iFieldName) = K_IM_TEST_MESSAGE_ID;
+ removeReplaceItem->iReplacementString = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iReplacementString) = K_IM_TEST_MESSAGE_ID_REPLACEMENT;
+ removeReplaceItem->iNumberFound=0;
+ iFieldList->AppendL(removeReplaceItem);
+
+ removeReplaceItem = new (ELeave) CImTestField;
+ removeReplaceItem->iFieldName = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iFieldName) = K_IM_TEST_CONTENT_ID;
+ removeReplaceItem->iReplacementString = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iReplacementString) = K_IM_TEST_CONTENT_ID_REPLACEMENT;
+ removeReplaceItem->iNumberFound=0;
+ iFieldList->AppendL(removeReplaceItem);
+
+ removeReplaceItem = new (ELeave) CImTestField;
+ removeReplaceItem->iFieldName = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iFieldName) = K_IM_TEST_BOUNDARY;
+ removeReplaceItem->iReplacementString = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iReplacementString) = K_IM_TEST_BOUNDARY_REPLACEMENT;
+ removeReplaceItem->iNumberFound=0;
+ iFieldList->AppendL(removeReplaceItem);
+
+ removeReplaceItem = new (ELeave) CImTestField;
+ removeReplaceItem->iFieldName = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iFieldName) = K_IM_TEST_HELO;
+ removeReplaceItem->iReplacementString = HBufC8::NewL(K_IM_TEST_STRING_MAX);
+ *(removeReplaceItem->iReplacementString) = K_IM_TEST_HELO_REPLACEMENT;
+ removeReplaceItem->iNumberFound=0;
+ iFieldList->AppendL(removeReplaceItem);
+
+ iFindReplaceList = new (ELeave) CArrayPtrFlat<CImFindReplace>(6);
+ }
+
+CScriptTestUtils::CScriptTestUtils(CEmailTestUtils& aTestUtils) : iTestUtils(aTestUtils)
+ {}
+
+
+CScriptTestUtils::TImLogLineType CScriptTestUtils::LineType(const HBufC8* aLine)
+ {
+ TImLogLineType lineType = EImLogLineComment;
+
+ if (aLine->Size() == 0)
+ {
+ lineType = EImEmptyLine;
+ }
+ else if (aLine->Size() > 19)
+ {
+ if ((((*aLine)[18]) == '<')
+ && (((*aLine)[19]) == '<'))
+ {
+ lineType = EImLogLineIn;
+ }
+ else if ((((*aLine)[18]) == '>')
+ && (((*aLine)[19]) == '>'))
+ {
+ lineType = EImLogLineOut;
+ }
+ else if ((aLine->Right(17)).Compare(K_IM_READ_CANCELLED) == 0)
+ {
+ lineType = EImReadCancelled;
+ }
+ }
+
+ return lineType;
+ }
+
+HBufC8* CScriptTestUtils::GetLineL(TFileReader& aFileReader)
+ {
+ TBuf8<2048> currentLine;
+ char character;
+ currentLine.Zero();
+
+
+ TBool crlfFound = EFalse;
+ TBool read = ETrue;
+
+ // Append characters one at a time until we reach a cr/lf pair or the end of the file.
+ while ((read) && (crlfFound == EFalse))
+ {
+ read = aFileReader.Read(character);
+
+ if (read)
+ {
+ if (0x0D == character)
+ {
+ read = aFileReader.Read(character);
+ if (read)
+ {
+ if (character == 0x0A)
+ {
+ crlfFound = ETrue;
+ }
+ else
+ {
+ // The cr was not part of the cr/lf pair so go back one space.
+ aFileReader.SeekCurrent(-1);
+ }
+ }
+ }
+
+ if ((read) && (EFalse == crlfFound))
+ {
+ currentLine.Append(character);
+ }
+ }
+ }
+
+ HBufC8* lineCopy;
+ if ((currentLine.Size() != 0) || (read))
+ {
+ lineCopy = HBufC8::NewL(2048);
+ (*lineCopy) = currentLine;
+ }
+ else
+ {
+ lineCopy = 0;
+ }
+
+ return lineCopy;
+ }
+
+
+CScriptTestUtils::TFileReader::TFileReader(RFile &rFile) : iFile(rFile), iBufferIndex(0), iBufferStart(0)
+ {
+ }
+
+TBool CScriptTestUtils::TFileReader::Read(char &rChar)
+ {
+ // Is the character we want not in the buffer ?
+ TBool read = ETrue;
+ if ((iBufferIndex >= iBuffer.Size())
+ || (iBufferIndex < 0))
+ // If it's not then get a new buffer starting at this position.
+ {
+ TInt seekPosition = iBufferIndex + iBufferStart;
+ TInt err = iFile.Seek(ESeekStart, seekPosition);
+ if (KErrNone != err)
+ {
+ iBuffer.SetLength(0);
+ read = EFalse;
+ }
+ else
+ {
+ iFile.Read(iBuffer);
+ if (iBuffer.Size() == 0)
+ {
+ read = EFalse;
+ }
+ iBufferStart += iBufferIndex;
+ iBufferIndex = 0;
+ }
+
+ if (iBuffer.Size() > 0)
+ {
+ rChar = iBuffer[0];
+ }
+ }
+ else
+ {
+ rChar = iBuffer[iBufferIndex];
+ }
+
+ if (read)
+ {
+ iBufferIndex++;
+ }
+
+ return read;
+ }
+
+void CScriptTestUtils::TFileReader::Seek(TInt aOffset)
+ {
+ iBufferIndex = aOffset;
+ iBuffer.Zero();
+ iBufferStart = 0;
+ }
+
+void CScriptTestUtils::TFileReader::SeekCurrent(TInt aOffset)
+ {
+ iBufferIndex += aOffset;
+ }
+
+
+CScriptTestUtils::~CScriptTestUtils()
+ {
+ delete iExpectedLine;
+ delete iActualLine;
+ iFieldList->ResetAndDestroy();
+ delete iFieldList;
+ iFindReplaceList->ResetAndDestroy();
+ delete iFindReplaceList;
+ }
+
+// Functions for checking the IM output.
+
+EXPORT_C TBool CScriptTestUtils::CheckLogOutputL(TInt aPortNumber, const TDesC& aTestFileName)
+ {
+ TBool matched = ETrue;
+
+ // Clear the old error values
+ delete iExpectedLine;
+ iExpectedLine = 0;
+ delete iActualLine;
+ iActualLine = 0;
+
+ RFile testFile; // The file to test against
+ RFile tempFile; // The stripped-down log file to test
+
+ // Create a temporary .out file from the log file.
+ TFileName logFileName;
+ logFileName.Format(K_IM_LOG_FILE_NAME, aPortNumber);
+
+ TParse tempFileName;
+ iTestUtils.ResolveLogFile(K_IM_LOG_TEMP_FILE_NAME, tempFileName);
+ LogToOutputFileL(logFileName, tempFileName.FullName(), ETrue);
+ tempFile.Close();
+
+ // Open the test file.
+ TInt err = testFile.Open(iTestUtils.FileSession(), aTestFileName, EFileShareReadersOnly);
+ TFileReader testFileReader(testFile);
+
+ // Open the temp file.
+ TParse tempLogFileName;
+ iTestUtils.ResolveLogFile(K_IM_LOG_TEMP_FILE_NAME, tempLogFileName);
+ err = tempFile.Open(iTestUtils.FileSession(), tempFileName.FullName(), EFileShareReadersOnly);
+ TFileReader tempFileReader(tempFile);
+
+ HBufC8* testLine = GetLineL(testFileReader);
+
+ if (testLine)
+ CleanupStack::PushL(testLine);
+
+ HBufC8* tempLine = GetLineL(tempFileReader);
+
+ if (tempLine)
+ CleanupStack::PushL(tempLine);
+
+ TInt lineNumber = 1;
+
+ while ((testLine != 0) && (tempLine != 0) && matched)
+ // Compare the specified .out file to the temporary one, line-by-line.
+ {
+ if (testLine->Des().Compare(tempLine->Des()) != 0)
+ {
+ matched = EFalse;
+ }
+
+ if (matched)
+ // If the lines didn't match then save the strings for later.
+ {
+ CleanupStack::PopAndDestroy(); // testLine
+ testLine = 0;
+ CleanupStack::PopAndDestroy(); // tempLine
+ tempLine = 0;
+ // Get the next line
+ testLine = GetLineL(testFileReader);
+ if (testLine)
+ CleanupStack::PushL(testLine);
+
+ tempLine = GetLineL(tempFileReader);
+ if (tempLine)
+ CleanupStack::PushL(tempLine);
+
+ lineNumber++;
+ }
+ }
+
+ if ((!matched) || (testLine != 0) || (tempLine != 0))
+ // Store the details if the files don't match.
+ {
+ // Set up the new error values
+ matched = EFalse;
+ iErrorLine = lineNumber;
+ TInt stringIndex;
+ if (testLine)
+ {
+ iExpectedLine = HBufC::NewL(testLine->Size());
+ // Copy the 8 bit buffer to the 16 bit buffer.
+ stringIndex = 0;
+ while (stringIndex < testLine->Size())
+ {
+ iExpectedLine->Des().Append((*testLine)[stringIndex]);
+ stringIndex++;
+ }
+ }
+ else
+ {
+ iExpectedLine = HBufC::NewL(((TDesC)K_IM_END_OF_FILE).Size());
+ (*iExpectedLine) = K_IM_END_OF_FILE;
+ }
+
+ if (tempLine)
+ {
+ iActualLine = HBufC::NewL(tempLine->Size());
+ // Copy the 8 bit buffer to the 16 bit buffer.
+ stringIndex = 0;
+ while (stringIndex < tempLine->Size())
+ {
+ iActualLine->Des().Append((*tempLine)[stringIndex]);
+ stringIndex++;
+ }
+ }
+ else
+ {
+ iActualLine = HBufC::NewL(((TDesC)K_IM_END_OF_FILE).Size());
+ (*iActualLine) = K_IM_END_OF_FILE;
+ }
+ }
+
+ if (tempLine)
+ CleanupStack::PopAndDestroy(); // tempLine
+
+ if (testLine)
+ CleanupStack::PopAndDestroy(); // testLine
+
+ testFile.Close();
+ tempFile.Close();
+
+ return matched;
+ }
+
+EXPORT_C TInt CScriptTestUtils::ErrorLineNumber()
+ {
+ return iErrorLine;
+ }
+
+EXPORT_C HBufC* CScriptTestUtils::ErrorExpectedL()
+ {
+ HBufC* stringCopy = HBufC::NewL(iExpectedLine->Size());
+ (*stringCopy) = (*iExpectedLine);
+ return stringCopy;
+ }
+
+EXPORT_C HBufC* CScriptTestUtils::ErrorActualL()
+ {
+ HBufC* stringCopy = HBufC::NewL(iActualLine->Size());
+ (*stringCopy) = (*iActualLine);
+ return stringCopy;
+ }