diff -r 000000000000 -r b16258d2340f applayerprotocols/httptransportfw/Test/t_httpmessage/cmessageparserdriver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerprotocols/httptransportfw/Test/t_httpmessage/cmessageparserdriver.cpp Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,632 @@ +// 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: +// + +#include "cmessageparserdriver.h" + +#include "mdriverobserver.h" +#include "cmessagedatasupplier.h" + +CMessageParserDriver* CMessageParserDriver::NewL(MDriverObserver& aObserver) + { + CMessageParserDriver* self = new(ELeave) CMessageParserDriver(aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CMessageParserDriver::~CMessageParserDriver() + { + Cancel(); + delete iDataSupplier; + iHeaders.Close(); + iTrailers.Close(); + iMessageParser.Close(); + } + +CMessageParserDriver::CMessageParserDriver(MDriverObserver& aObserver) +: CActive(CActive::EPriorityStandard), iObserver(aObserver) + { + CActiveScheduler::Add(this); + } + +void CMessageParserDriver::ConstructL() + { + iMessageParser.OpenL(*this); + } + +void CMessageParserDriver::SetMessageData(const TDesC8& aMessageData) + { + iMessageData.Set(aMessageData); + } + +void CMessageParserDriver::SetStartLine(const TDesC8& aStartLine) + { + iStartLine.Set(aStartLine); + } + +void CMessageParserDriver::SetHeaderL(const TDesC8& aFieldName, const TDesC8& aFieldValue) + { + User::LeaveIfError(iHeaders.Append(THeaderField(aFieldName, aFieldValue))); + } + +void CMessageParserDriver::SetBodyData(const TDesC8& aBodyData, TBool aIsChunked, TBool aIsUnknownLength) + { + iEntityBody.Set(aBodyData); + iIsUnknownLength = aIsUnknownLength; + + // Set the entity body info + if( iEntityBody.Length() > 0 ) + { + if( aIsChunked ) + { + iExpectBodyState = EChunkEncodedBody; + } + else + { + if( iIsUnknownLength ) + iExpectBodyState = EUnknownBodyLength; + else + iExpectBodyState = ENonEncodedBody; + } + } + else + { + iExpectBodyState = ENoEntityBody; + } + } + +void CMessageParserDriver::SetTrailerL(const TDesC8& aFieldName, const TDesC8& aFieldValue) + { + User::LeaveIfError(iTrailers.Append(THeaderField(aFieldName, aFieldValue))); + } + +void CMessageParserDriver::Start(TInt aExpectedError, TBool aTestReset) + { + iExpectedError = aExpectedError; + iDoReset = aTestReset; + + // Inform the observer that the test has started + iObserver.NotifyStart(); + + // Initially set the buffer size to the length of the message unless doing + // reset test - use a buffer size of an eighth of the message size + if( iDoReset ) + { + iBufferSize = iMessageData.Length()/8; + if( iBufferSize < 1 ) + iBufferSize = 1; + } + else + iBufferSize = iMessageData.Length(); + + // Set the reset state to initial state - PendingStartLine. + iResetState = EPendingStartLine; + + // Self-complete to kick-off the test. + CompleteSelf(); + } + +void CMessageParserDriver::CompleteSelf() + { + TRequestStatus* pStat = &iStatus; + User::RequestComplete(pStat, KErrNone); + SetActive(); + } + +void CMessageParserDriver::DoReset() + { + // Reset the parser and update the reset state. + iMessageParser.Reset(); + iResetState = iState; + + iObserver.Log(_L("RESET - starting test again!!")); + + // Reset the data supplier + delete iDataSupplier; + iDataSupplier = NULL; + + if( iState == EPendingHeaders ) + iResetIndex = iHeaderIndex; + else if( iState == EPendingTrailers ) + iResetIndex = iTrailerIndex; + else if( iState == EPendingBodySize ) + iResetIndex = 0; + else if( iState == EPendingBody ) + iResetIndex = iBodyIndex; + + // Start the test over... + CompleteSelf(); + } + +/* + * Methods from CActive + */ + +void CMessageParserDriver::RunL() + { + // Reset the test case data + iHeaderIndex = 0; + iTrailerIndex = 0; + iExpectBodyData.Set(iEntityBody); + + // Set the reset flags + iReset = EFalse; + iBodyIndex = 0; + iChunkCount = 0; + + // Reset the data supplier + delete iDataSupplier; + iDataSupplier = NULL; + + iDataSupplier = CMessageDataSupplier::NewL(*this, iMessageData, iBufferSize); + + TBuf<64> comment; + comment.Format(_L("STARTING PARSING -> buffer size : %d"), iBufferSize); + iObserver.Log(comment); + + // Start the parser... + iMessageParser.ReceivedMessageData(); + + // Move to PendingStartLine state... + iState = EPendingStartLine; + } + +void CMessageParserDriver::DoCancel() + { + // Do nothing... + } + +TInt CMessageParserDriver::RunError(TInt aError) + { + // Inform the observer of the error + iObserver.NotifyError(aError); + return KErrNone; + } + +/* + * Methods from MHttpMessageParserObserver + */ + +void CMessageParserDriver::GetDataPacket(TPtrC8& aData) + { + __ASSERT_DEBUG( iTestFailed == EFalse, User::Invariant() ); + + if( iReset ) + { + // Not expecting a header. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting GetDataPacket")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + + iDataSupplier->GetData(aData); + } + +void CMessageParserDriver::ReleaseDataPacket() + { + __ASSERT_DEBUG( iTestFailed == EFalse, User::Invariant() ); + + if( iReset ) + { + // Not expecting a header. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting ReleaseDataPacket")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + + iDataSupplier->ReleaseData(); + + // If we have recieved all the data and we were doing a 1.0 request of unknown length + // tell the parser the data is complete and we are waiting for the body to be complete. + if( iExpectBodyData.Length() == 0 && iIsUnknownLength && iState==EPendingBodyComplete) + { + TRAPD(err, iMessageParser.CompletedBodyDataL() ); + if( err != KErrNone ) + { + // Not expecting a header. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting ReleaseDataPacket")); + iObserver.NotifyError(err); + iTestFailed = ETrue; + } + } + + } + +void CMessageParserDriver::StartLineL(const TDesC8& aStartLine) + { + __ASSERT_DEBUG( iTestFailed == EFalse, User::Invariant() ); + + iObserver.Log(_L("Start-line received")); + TBuf<256> comment; + comment.Copy(aStartLine); + iObserver.Log(comment); + + // Was start-line expected? + if( iState != EPendingStartLine || iReset ) + { + // Not expecting start-line. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting start-line")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + else + { + // Check that the start-line is correct. + if( aStartLine.Compare(iStartLine) == 0 ) + { + // Should a reset occur here? + if( iDoReset && iResetState == iState ) + iReset = ETrue; + + // Match - what is next? + if( iHeaders.Count() == 0 ) + iState = EPendingBodySize; + else + iState = EPendingHeaders; + // We no longer parse line by line. We parse startline & headers (5) at one go. + // We cannot reset here + iReset = EFalse; + // Reset? + if( iDoReset && iReset ) + DoReset(); + } + else + { + // The start-line does not match. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - received incorrect start-line")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + } + } + +void CMessageParserDriver::HeaderL(const TDesC8& aFieldName, TDesC8& aFieldValue) + { + __ASSERT_DEBUG( iTestFailed == EFalse, User::Invariant() ); + + iObserver.Log(_L("HeaderL received")); + + // Was a header expected? NOTE - this can be a trailer header... + if( (iState != EPendingHeaders && iState != EPendingTrailers) || iReset ) + { + // Not expecting a header. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting HeaderL")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + else + { + // Yep - log the parsed header... + TBuf<64> name; + name.Copy(aFieldName); + TBuf<256> value; + value.Copy(aFieldValue); + TBuf<322> comment; + comment.Format(_L("%S: %S"), &name, &value); + iObserver.Log(comment); + + // Get the expected header info... + THeaderField header; + if( iState == EPendingHeaders ) + { + // Should a reset occur here? + if( iDoReset && (iResetState == iState && iResetIndex == iHeaderIndex) ) + iReset = ETrue; + + // Get the current header info... + header = iHeaders[iHeaderIndex]; + + // Loop to next header... + ++iHeaderIndex; + + // Set next state... + if( iHeaderIndex < iHeaders.Count() ) + iState = EPendingHeaders; + else + iState = EPendingBodySize; + } + else + { + // Should a reset occur here? + if( iDoReset && (iResetState == iState && iResetIndex == iTrailerIndex) ) + iReset = ETrue; + + // Get the current trailer info... + header = iTrailers[iTrailerIndex]; + + // Loop to next header... + ++iTrailerIndex; + + // Set next state... + if( iTrailerIndex < iTrailers.Count() ) + iState = EPendingTrailers; + else + iState = EPendingMessageComplete; + } + TPtrC8 expectedName = header.iName; + TPtrC8 expectedValue = header.iValue; + + // Check that the parsed header info matches expected + if( expectedName.Compare(aFieldName) != 0 || expectedValue.Compare(aFieldValue) != 0 ) + { + // The header info does not match. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - received incorrect header info")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + else if( iDoReset && iReset ) + DoReset(); + } + } + +TInt CMessageParserDriver::BodySizeL() + { + __ASSERT_DEBUG( iTestFailed == EFalse, User::Invariant() ); + + // Log the headers complete event + iObserver.Log(_L("BodySizeL received")); + + // Was this expected? + TInt size = MHttpMessageParserObserver::ENoBody; + if( iState != EPendingBodySize || iReset ) + { + // Not expected! Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting BodySizeL")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + else + { + // Should a reset occur here? + if( iDoReset && iResetState == iState ) + iReset = ETrue; + + // Yep - workout what is next... + switch( iExpectBodyState ) + { + case ENoEntityBody: + { + // No body - use default value of size + iState = EPendingMessageComplete; + } break; + case EChunkEncodedBody: + { + // There is a body that is chunk encoded. + size = MHttpMessageParserObserver::EChunked; + iState = EPendingBody; + } break; + case ENonEncodedBody: + { + // There is a body that is not encoded. + size = iExpectBodyData.Length(); + iState = EPendingBody; + } break; + case EUnknownBodyLength: + { + // There is a body of unknown length + size = MHttpMessageParserObserver::EUnknown; + iState = EPendingBody; + } break; + default: + User::Invariant(); + break; + } + + // Reset? + if( iDoReset && iReset ) + DoReset(); + } + return size; + } + +void CMessageParserDriver::BodyChunkL(const TDesC8& aData) + { + __ASSERT_DEBUG( iTestFailed == EFalse, User::Invariant() ); + + iObserver.Log(_L("BodyChunkL received")); + + // Was this expected? + if( iExpectBodyState != EChunkEncodedBody && (iState != EPendingBody || iReset )) + { + // No body data expected. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting BodyChunkL")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + else + { + // Dump the body data... + iObserver.Dump(aData); + + // Check to see if it matches the expected data. + TBool match = EFalse; + if( aData.Length() <= iExpectBodyData.Length() ) + { + // Is the content the same + if( aData.Compare(iExpectBodyData.Left(aData.Length())) == 0 ) + { + // Data is the same - update the expected data + iExpectBodyData.Set(iExpectBodyData.Mid(aData.Length())); + match = ETrue; + } + } + if( match ) + { + // Should a reset occur here? + if( iDoReset && (iResetState == iState && iResetIndex == iBodyIndex) ) + iReset = ETrue; + + ++iBodyIndex; + + // Has all the data been received? + if( iExpectBodyData.Length() == 0 ) + iState = EPendingBodyComplete; + + // Reset? + if( iDoReset && iReset ) + DoReset(); + } + else + { + // The body data does not match. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - received incorrect body data")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + } + } + +void CMessageParserDriver::BodyCompleteL() + { + __ASSERT_DEBUG( iTestFailed == EFalse, User::Invariant() ); + + iObserver.Log(_L("BodyCompleteL received")); + + // Was this expected? + if( iState != EPendingBodyComplete || iReset ) + { + // Not expecting body complete. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting BodyCompleteL")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + else + { + // Should a reset occur here? + if( iDoReset && iResetState == iState ) + iReset = ETrue; + + // What's next? + if( iExpectBodyState == EChunkEncodedBody && iTrailers.Count() > 0 ) + iState = EPendingTrailers; + else + iState = EPendingMessageComplete; + + // Reset? + if( iDoReset && iReset ) + DoReset(); + } + } + +void CMessageParserDriver::MessageCompleteL(const TPtrC8& /*aExcessData*/) + { + __ASSERT_DEBUG( iTestFailed == EFalse, User::Invariant() ); + + // Log the message complete event + iObserver.Log(_L("Message Complete")); + + // Was this expected? + if( iState != EPendingMessageComplete || iReset ) + { + // Not expecting message complete. Test has failed - notify the observer. + iObserver.Log(_L("FAIL - not expecting message complete")); + iObserver.NotifyError(KErrNotFound); + iTestFailed = ETrue; + } + else + { + // Should a reset occur here? + if( iDoReset && iResetState == iState ) + iReset = ETrue; + + // Next state... + iState = EDone; + + // Reset? Or is the buffer size small enough? + if( iDoReset && iReset ) + DoReset(); + else if( !iDoReset && iBufferSize > 1 ) + { + // Nope - half and do test again!! + iBufferSize /= 2; + iResetState = EPendingStartLine; + CompleteSelf(); + + iObserver.Log(_L("RE-PARSE WITH SMALLER BUFFER")); + } + else + { + // Yep - test done... + iObserver.NotifyComplete(); + } + } + } + +TInt CMessageParserDriver::HandleParserError(TInt aError) + { + // Is an error expected? + if( iExpectedError == aError ) + { + TBuf<64> comment; + comment.Format(_L("Received expected error : %d"), aError); + iObserver.Log(comment); + + // Yep and received expected - is the buffer size small enough? + if( !iDoReset && iBufferSize > 1 ) + { + // Nope - halve and do test again!! + iBufferSize /= 2; + CompleteSelf(); + + iObserver.Log(_L("RE-PARSE WITH SMALLER BUFFER")); + } + else + { + // Yep - test done... + iObserver.NotifyComplete(); + } + } + else + { + // Inform the observer of the error + iObserver.NotifyError(aError); + } + return KErrNone; + } + +void CMessageParserDriver::Reserved_MHttpMessageParserObserver() + { + User::Invariant(); + } + +/* + * Methods from MDataSupplierObserver + */ + +void CMessageParserDriver::DataReady() + { + if( iDoReset && iChunkIndex == iChunkCount ) + { + // Reset the parser and update the chunk index + iMessageParser.Reset(); + ++iChunkIndex; + + iObserver.Log(_L("RESET - starting test again!!")); + + // Reset the data supplier + delete iDataSupplier; + iDataSupplier = NULL; + + // Start the test over... + CompleteSelf(); + } + else + { + // Inc the chunk count and notify the parser of more data + ++iChunkCount; + iMessageParser.ReceivedMessageData(); + } + }