diff -r eb9b28acd381 -r 2f10d260163b contentmgmt/cafstreamingsupport/test/tscaf/source/tscafstep.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contentmgmt/cafstreamingsupport/test/tscaf/source/tscafstep.cpp Mon Mar 15 12:46:43 2010 +0200 @@ -0,0 +1,827 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "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: +// Implements the basic test step for the Streaming CAF test harness +// +// + +#include "tscafstep.h" +#ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY +#include +#include +#endif + +TSdpAttribute::TSdpAttribute() + { + } + +CTestDecoderConfiguration* CTestDecoderConfiguration::NewLC() + { + CTestDecoderConfiguration* self = new (ELeave) CTestDecoderConfiguration(); + CleanupStack::PushL(self); + return self; + } + +CTestDecoderConfiguration::~CTestDecoderConfiguration() + { + iAttributeArray.Close(); + } + +CTestDecoderConfiguration::CTestDecoderConfiguration() + { + } + +TExpectedKeyStreamDecoderAttributes::TExpectedKeyStreamDecoderAttributes() + { + } + +CScafStep::CScafStep(CScafServer& aParent) +/** + Constructor. + */ + : iParent(aParent), iThreadId(0), iOOMTest(EFalse) + { + //empty + } + +CScafStep::~CScafStep() +/** + Destructor. + */ + { + //empty + } + + +TVerdict CScafStep::doTestStepPreambleL() +/** + From CTestStep. Creates an active scheduler for the test step. + */ + { + __UHEAP_MARK; + INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells()); + + iActiveScheduler = new (ELeave) CActiveScheduler; + CActiveScheduler::Install(iActiveScheduler); + + ReadTestConfigurationL(); + + SetTestStepResult(EPass); + return TestStepResult(); + } + +TVerdict CScafStep::doTestStepL() +/** + * From CTestStep. Default behaviour of doTestStepL() allows for the test case to be run both + * under 'Normal' and 'Out of Memory' Conditions. + * + * Implementation of the test case itself is called from the doTestL() of the derived test step. + * + * The state of the iOOMTest member variable determines the type of test conditons: + * EFalse - Normal Test + * ETrue - Out of Memory Test + */ + { + if (!iOOMTest) + { + doTestL(); + } + else + { + doOOMTestL(); + } + + return TestStepResult(); + } + +TVerdict CScafStep::doTestStepPostambleL() +/** + From CTestStep. Destroys the active scheduler of the test step. + */ + { + CActiveScheduler::Install(NULL); + delete iActiveScheduler; + + iDecoderConfigurationArray.ResetAndDestroy(); + iExpectedKeyStreamDecoderData.Close(); + + INFO_PRINTF2(_L("HEAP CELLS: %d"),User::CountAllocCells()); + __UHEAP_MARKEND; + + return TestStepResult(); + } + +#ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY +// We need this dummy function because TCleanupItem c'tor (see below) does not accept functions without parameters +void CloseSdpCodecPool(TAny *) + { + SdpCodecStringPool::Close(); + } + +CSdpDocument* CScafStep::CreateSdpDocumentLC() +/** + Creates an SDP document object which is a collection of all media fields and session attributes. + @return A pointer to the SDP document object. + The ownership is transferred. Please note that + the returned object must be deleted by DeleteSdpAndCloseCodecPool method. + */ + { + // Open the string pool to access all predefined SDP constants + SdpCodecStringPool::OpenL(); + CleanupStack::PushL(TCleanupItem(CloseSdpCodecPool,this)); //Pass the class pointer to make armv5 compiler (for urel) happy + + // Create the CSdpDocument object + CSdpDocument* sdpDocument = CSdpDocument::NewLC(); + + // Define the session name + sdpDocument->SetSessionNameL(_L8("ScafTest")); + + // Set the origin field. The values are not important. + // Because they are not used in our tests. + TInt64 sessionId(TUint(2055478987)); + TInt64 sessionVersion(TUint(2027813655)); + TInetAddr address; + const TUint32 KInetAddr = INET_ADDR(192,168,0,3); + address.SetAddress( KInetAddr ); + CSdpOriginField* originField = CSdpOriginField::NewLC(_L8("scafuser"), sessionId, sessionVersion, address); + sdpDocument->SetOriginField(originField); + CleanupStack::Pop(originField); + + CleanupStack::Pop(); // Pop the temporary guard on SDP Codec string pool close + CleanupStack::Pop(); // Pop sdpDocument object + CleanupStack::PushL(TCleanupItem(CScafStep::DeleteSdpDocAndCloseCodecPool, reinterpret_cast(sdpDocument))); + + return sdpDocument; + } + +void CScafStep::AddMediaFieldL(CSdpDocument& aSdpDoc, const CSdpMediaField* aSdpKeyStream) +/** + Adds an SDP media field object to a given SDP document object. + @param aSdpDoc The SDP document object + @param aSdpKeyStream Sdp media field which will be appended to the SDP document object. + This object should be popped from the cleanupstack after this function runs successfully. + */ + { + // Set the key stream field given + User::LeaveIfError(aSdpDoc.MediaFields().Append(aSdpKeyStream)); + } + +CSdpMediaField* CScafStep::CreateSdpLC(TInt aSdpNum) +/** + Creates a simple SDP media field object. + @param aSdpNum An integer representing the accessor to the SDP parameter + array and the required data + @return A pointer to the SDP media field object. + The ownership is transferred. Please note that + the returned object must be deleted by DeleteSdpAndCloseCodecPool method. + @see CScafStep::DeleteSdp + */ + { + TPtrC pMedia; + pMedia.Set(iDecoderConfigurationArray[aSdpNum]->iMedia); + + TInt mIndex = 0; + if(!pMedia.CompareF(KSdpMediaAudio)) + { + mIndex = SdpCodecStringConstants::EMediaAudio; + } + else if(!pMedia.CompareF(KSdpMediaVideo)) + { + mIndex = SdpCodecStringConstants::EMediaVideo; + } + else if(!pMedia.CompareF(KSdpMediaData)) + { + mIndex = SdpCodecStringConstants::EMediaData; + } + else + { + ERR_PRINTF2(_L("Unsupported media type: '%S'"),&pMedia); + SetTestStepResult(EFail); + User::Leave(KErrNotFound); + } + + TPtrC pProtocol; + pProtocol.Set(iDecoderConfigurationArray[aSdpNum]->iProtocol); + + TInt mProtocol = 0; + if(!pProtocol.CompareF(KSdpProtocolUdp)) + { + mProtocol = SdpCodecStringConstants::EProtocolUdp; + } + else if(!pProtocol.CompareF(KSdpProtocolTcp)) + { + mProtocol = SdpCodecStringConstants::EProtocolTcp; + } + else if(!pProtocol.CompareF(KSdpProtocolRtp)) + { + mProtocol = SdpCodecStringConstants::EProtocolRtpAvp; + } + else + { + ERR_PRINTF2(_L("Unsupported protocol type: '%S'"),mProtocol); + SetTestStepResult(EFail); + User::Leave(KErrNotFound); + } + + TInt port = iDecoderConfigurationArray[aSdpNum]->iPort; + + TPtrC pFormat; + pFormat.Set(iDecoderConfigurationArray[aSdpNum]->iFormat); + + //Convert 16-bit to 8-bit + TPtr8 ptrFormat(Convert16To8LC(pFormat)); + + RStringPool pool = SdpCodecStringPool::StringPoolL(); + RStringF mediaData = pool.StringF(mIndex, SdpCodecStringPool::StringTableL()); + CleanupClosePushL(mediaData); + RStringF protocol = pool.StringF(mProtocol, SdpCodecStringPool::StringTableL()); + CleanupClosePushL(protocol); + + CSdpMediaField* sdp = CSdpMediaField::NewL(mediaData, port, protocol, ptrFormat); + CleanupStack::PopAndDestroy(3); + CleanupStack::PushL(sdp); + + //If a connection address is defined, create an SDP connection field and add it to the SDP media field + if(iDecoderConfigurationArray[aSdpNum]->iConnAddr.Length()>0) + { + //The only supported network type is ENetType + RStringF netType = pool.StringF(SdpCodecStringConstants::ENetType, SdpCodecStringPool::StringTableL()); + CleanupClosePushL(netType); + //The only supported address type is IP v4 + RStringF addressType = pool.StringF(SdpCodecStringConstants::EAddressTypeIP4, SdpCodecStringPool::StringTableL()); + CleanupClosePushL(addressType); + //Create the connection field + CSdpConnectionField* connField = CSdpConnectionField::NewL(netType, addressType, Convert16To8LC(iDecoderConfigurationArray[aSdpNum]->iConnAddr)); + CleanupStack::PushL(connField); + //Set the connection field into the SDP media field + sdp->ConnectionFields().AppendL(connField); + CleanupStack::Pop(connField); + CleanupStack::PopAndDestroy(3, &netType); //netType, addressType, Convert16To8LC + } + + //Add atrributes + AddAttributes2SdpL(*sdp, aSdpNum); + + return sdp; + } +#endif + +CKeyStreamSink* CScafStep::CreateKeyStreamSinkLC(const TDesC& aFileName, const TDesC& aPrivPath) +/** + Creates a test key stream sink object. + @param aFilePath The output file name of the test key stream sink. + @param aPrivPath Stream Agents Private Folder Path + @return A pointer to the test key stream sink object. + The ownership is transferred. + */ + { + HBufC* privFolder = GetFullPathLC(aPrivPath, aFileName); + CTestKeyStreamSink* sink = CTestKeyStreamSink::NewL(*privFolder); + CleanupStack::PopAndDestroy(privFolder); + CleanupStack::PushL(sink); + return sink; + } + +void CScafStep::CleanAgentsPrivateFolderL(const TDesC& aPrivatePath) +/** + Delete all files and folders under the private directory of the test agent. + */ + { + HBufC* agentPrivFol = GetFullPathLC(aPrivatePath, _L("*.*")); + CFileMan *fm = CFileMan::NewL(iParent.Fs()); + CleanupStack::PushL(fm); + + TInt ret = fm->Delete(*agentPrivFol,0); + if((ret != KErrNone)&&(ret != KErrNotFound)&&(ret != KErrPathNotFound)) + { + User::Leave(ret); + } + CleanupStack::PopAndDestroy(2, agentPrivFol); + } + + +void CScafStep::DeleteSdpDocAndCloseCodecPool(TAny* aSdpDoc) +/** + Delete the SDP document object and close the codec pool + @param aSdp The SDP object which will be deleted. + */ + { +#ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY + delete reinterpret_cast(aSdpDoc); + SdpCodecStringPool::Close(); +#else + (void) aSdpDoc; +#endif + } + +void CScafStep::CopyFile2AgentsPrivateFolderL(RFs& aFs, const TDesC& aFileName, const TDesC& aPrivPath) +/** + Copy a test file from Z drive to the private folder of the test agent server. + @param aFs File Server session. + @param aPrivPath Stream Agents Private Folder Path + @param aFileName The name of the file which lives in the folder of Z drive. + */ + { + //Gets the target file path + HBufC* fTarget = GetFullPathLC(aPrivPath, aFileName); + //Make sure that the path exists + TInt err = aFs.MkDirAll(*fTarget); + if(err != KErrNone && err != KErrAlreadyExists) + { + User::Leave(err); + } + + //Get the file source path + TFileName fSource(KDataFilesPath); + fSource.Append(aFileName); + + //Create a file manager + CFileMan *fm = CFileMan::NewL(aFs); + CleanupStack::PushL(fm); + + //Copy the source file to the target + User::LeaveIfError(fm->Copy(fSource, *fTarget)); + // Make the file writeable + User::LeaveIfError(fm->Attribs(*fTarget, 0, KEntryAttReadOnly, TTime(0), 0)); + CleanupStack::PopAndDestroy(2, fTarget); + } + +#ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY +void CScafStep::AddAttributes2SdpL(CSdpMediaField& aSdp, TInt aSdpNum) +/** + * Add attributes from the instance within the CSdpConfiguration array, where + * the attribute information is stored, into the SDP object being constructed. + * @param aSdp The SDP object where the attribute is added. + */ + { + TInt attrCount = iDecoderConfigurationArray[aSdpNum]->iAttributeArray.Count(); + + RStringPool pool = SdpCodecStringPool::StringPoolL(); + + for(TInt i=0; i < attrCount; ++i) + { + TPtrC pAttrType; + pAttrType.Set(iDecoderConfigurationArray[aSdpNum]->iAttributeArray[i].iAttributeType); + + TPtrC pAttrName; + pAttrName.Set(iDecoderConfigurationArray[aSdpNum]->iAttributeArray[i].iAttributeName); + + //Convert 16-bit to 8-bit + TPtr8 ptrAttrName(Convert16To8LC(pAttrName)); + + TPtrC pAttrValue; + pAttrValue.Set(iDecoderConfigurationArray[aSdpNum]->iAttributeArray[i].iAttributeValue); + + //Convert 16-bit to 8-bit + TPtr8 ptrAttrValue(Convert16To8LC(pAttrValue)); + + if(pAttrType.Compare(_L("Format"))) + { + RStringF attrName = pool.OpenFStringL(ptrAttrName); + CleanupClosePushL(attrName); + CSdpAttributeField *attribute = CSdpAttributeField::NewLC(attrName, ptrAttrValue); + User::LeaveIfError((aSdp.AttributeFields()).Append(attribute)); + CleanupStack::Pop(attribute); + } + else + { + RStringF fmtpStr = pool.StringF(SdpCodecStringConstants::EAttributeFmtp, SdpCodecStringPool::StringTableL()); + CleanupClosePushL(fmtpStr); + CSdpFmtAttributeField* fmtpAttribute = CSdpFmtAttributeField::NewLC(fmtpStr, ptrAttrName, ptrAttrValue); + User::LeaveIfError(aSdp.FormatAttributeFields().Append(fmtpAttribute)); + CleanupStack::Pop(fmtpAttribute); + } + CleanupStack::PopAndDestroy(3); + }//for + }//End of function +#endif + +void CScafStep::PrintErrorAndLeaveL(TDesC& aKey) +/** + Prints an error message and then leaves with not found error. + @param aKey The name of the key which is not found. + */ + { + ERR_PRINTF2(_L("Failed to read '%S' key of configuration"), &aKey); + SetTestStepResult(EFail); + User::Leave(KErrNotFound); + } + +TPtr8 CScafStep::Convert16To8LC(TDesC& aDes) +/** + Convert a 16-bit descriptor into 8-bit. + @param aVal The 16-bit descriptor. + @return The descriptor converted to 8-bit. + */ + { + HBufC8* buf = HBufC8::NewLC(aDes.Size()); + TPtr8 ptr(buf->Des()); + ptr.Copy(aDes); + return ptr; + } + +HBufC* CScafStep::GetFullPathLC(const TDesC& aPath, const TDesC& aFileName) +/** + Create a fully qualified file path. + @param aPath The folder path of the file. + @param aFileName The name of the file. + @return A pointer to the fully qualified file path. + */ + { + HBufC* fullPath = HBufC::NewLC(aPath.Length()+aFileName.Length()+1); + TPtr ptr(fullPath->Des()); + ptr.Copy(aPath); + ptr[0] = iParent.Fs().GetSystemDriveChar(); + if(aFileName.Length()>0) + { + ptr.Append(aFileName); + } + return fullPath; + } + +CSraRightsObject* CScafStep::GetRightsObjectLC(const TDesC& aName, const TDesC& aPrivPath) +/** + Reads the given RO file and creates a RO object. + @param aName The name of the RO file. + @param aPrivPath Stream Agents Private Folder Path + @return The RO object. + */ + { + RFile f; + HBufC* path = GetFullPathLC(aPrivPath, aName); + User::LeaveIfError(f.Open(iParent.Fs(), *path, EFileRead)); + CleanupStack::PopAndDestroy(path); + CleanupClosePushL(f); + RFileReadStream stream(f); + CleanupClosePushL(stream); + CSraRightsObject* ro = CSraRightsObject::NewL(stream); + CleanupStack::PopAndDestroy(2, &f); + CleanupStack::PushL(ro); + return ro; + } + +TVerdict CScafStep::doOOMTestL() +/** + * Runs the test step under OOM Conditions checking that each heap allocation is fail safe + */ + { + // Pre and Post test heap cell allocation counts + TInt cellCountAfter = 0; + TInt cellCountBefore = 0; + + /** + * The loop tests each heap allocation under out of memory conditions to determine whether + * the framework cleans up correctly without leaking memory. + * + * The 'for' loop does not have any completion criteria, so the loop breaks out as soon + * as any of the following events occur: + * a) The pre and post heap cell counts mismatch signalling a memory leakage + * b) An unexpected leave (any leave with an error code other than 'KErrNoMemory') + * c) All heap allocations have been tested and the test returns 'KErrNone' + */ + for (TInt testCount = 0; ; ++testCount) + { + __UHEAP_MARK; + __UHEAP_SETFAIL(RHeap::EDeterministic, testCount+1); + cellCountBefore = User::CountAllocCells(); + TRAPD(err, doTestL()); + cellCountAfter = User::CountAllocCells(); + __UHEAP_MARKEND; + + INFO_PRINTF3(_L("OOM Test %d: Status = %d"),testCount,err); + + if (err == KErrNone) + { + INFO_PRINTF1(_L("OOM Test Finished")); + break; + } + else if(err == KErrNoMemory) + { + if (cellCountBefore != cellCountAfter) + { + ERR_PRINTF2(_L("OOM Test Result: Failed - Memory leakage on iteration %d"), testCount); + ERR_PRINTF2(_L("Pre-Test Heap Cell Count: %d"), cellCountBefore); + ERR_PRINTF2(_L("Post-Test Heap Cell Count: %d"), cellCountAfter); + SetTestStepResult(EFail); + break; + } + } + else + { + User::Leave(err); + break; + } + } + + return TestStepResult(); + } + +TVerdict CScafStep::doTestL() + { + return TestStepResult(); + } + +void CScafStep::ReadTestConfigurationL() + { + TInt baseIndex=0; + + // Read SDP Configuration Data + TName fMedia; + TName fProtocol; + TName fPort; + TName fFormat; + TName fConnAddr; + + fMedia.Format(KSdpMedia, baseIndex); + fProtocol.Format(KSdpProtocol, baseIndex); + fPort.Format(KSdpPort, baseIndex); + fFormat.Format(KSdpFormat, baseIndex); + fConnAddr.Format(KSdpConnAddr, baseIndex); + + TPtrC mediaData; + TPtrC protocolData; + TInt portData; + TPtrC formatData; + TPtrC connAddrData; + + while (GetStringFromConfig(ConfigSection(), fMedia, mediaData) && + GetStringFromConfig(ConfigSection(), fProtocol, protocolData) && + GetIntFromConfig(ConfigSection(), fPort, portData) && + GetStringFromConfig(ConfigSection(), fFormat, formatData)) + { + + CTestDecoderConfiguration* newSdpConfig = CTestDecoderConfiguration::NewLC(); + + newSdpConfig->iMedia.Set(mediaData); + newSdpConfig->iProtocol.Set(protocolData); + newSdpConfig->iPort = portData; + newSdpConfig->iFormat.Set(formatData); + + if(GetStringFromConfig(ConfigSection(), fConnAddr, connAddrData)) + { + newSdpConfig->iConnAddr.Set(connAddrData); + } + + // Read Stream Associated Agents Private Folder Path + TName fPrivateFolderPath; + TName fSingleProcessAgent; + + fPrivateFolderPath.Format(KScafConfigPrivateFolderPath, baseIndex); + fSingleProcessAgent.Format(KScafConfigSingleProcessAgent, baseIndex); + + TPtrC privateFolderPath; + TBool singleProcessAgent; + + if(GetStringFromConfig(ConfigSection(), fPrivateFolderPath, privateFolderPath) && + GetBoolFromConfig(ConfigSection(), fSingleProcessAgent, singleProcessAgent)) + { + newSdpConfig->iPrivateFolderPath.Set(privateFolderPath); + newSdpConfig->iSingleProcessAgent = singleProcessAgent; + } + + // Read SDP Attribute Data + TInt attributeIndex = 0; + + TName fAttributeType; + TName fAttributeName; + TName fAttributeValue; + + fAttributeType.Format(KSdpAttributeType,baseIndex,attributeIndex); + fAttributeName.Format(KSdpAttributeName,baseIndex,attributeIndex); + fAttributeValue.Format(KSdpAttributeValue,baseIndex,attributeIndex); + + TPtrC attributeType; + TPtrC attributeName; + TPtrC attributeValue; + + while (GetStringFromConfig(ConfigSection(), fAttributeType, attributeType) && + GetStringFromConfig(ConfigSection(), fAttributeName, attributeName) && + GetStringFromConfig(ConfigSection(), fAttributeValue, attributeValue)) + { + TSdpAttribute newAttribute; + + newAttribute.iAttributeType.Set(attributeType); + newAttribute.iAttributeName.Set(attributeName); + newAttribute.iAttributeValue.Set(attributeValue); + + newSdpConfig->iAttributeArray.Append(newAttribute); + + attributeIndex++; + fAttributeType.Format(KSdpAttributeType,baseIndex,attributeIndex); + fAttributeName.Format(KSdpAttributeName,baseIndex,attributeIndex); + fAttributeValue.Format(KSdpAttributeValue,baseIndex,attributeIndex); + } + + iDecoderConfigurationArray.Append(newSdpConfig); + + CleanupStack::Pop(newSdpConfig); + + baseIndex++; + fMedia.Format(KSdpMedia, baseIndex); + fProtocol.Format(KSdpProtocol, baseIndex); + fPort.Format(KSdpPort, baseIndex); + fFormat.Format(KSdpFormat, baseIndex); + fConnAddr.Format(KSdpConnAddr, baseIndex); + } + + // Read Expected Key Stream Decoder Attribute Values + TName fIsProgramProtected; + TName fIsServiceProtected; + TName fCanExport; + TName fMustProtectIfRecording; + TName fCanPlay; + TName fContentId; + TName fRightsIssuerUri; + + baseIndex = 0; + + fIsProgramProtected.Format(KScafConfigIsProgramProtected,baseIndex); + fIsServiceProtected.Format(KScafConfigIsServiceProtected,baseIndex); + fCanExport.Format(KScafConfigCanExport,baseIndex); + fMustProtectIfRecording.Format(KScafConfigMustProtectIfRecording,baseIndex); + fCanPlay.Format(KScafConfigCanPlay,baseIndex); + fContentId.Format(KScafConfigContentId,baseIndex); + fRightsIssuerUri.Format(KScafConfigRightsIssuerUri,baseIndex); + + TBool isProgramProtected; + TBool isServiceProtected; + TBool canExport; + TBool mustProtectIfRecording; + TBool canPlay; + TPtrC contentId; + TPtrC rightsIssuerUri; + + while(GetBoolFromConfig(ConfigSection(),fIsProgramProtected,isProgramProtected) && + GetBoolFromConfig(ConfigSection(),fIsServiceProtected,isServiceProtected) && + GetBoolFromConfig(ConfigSection(),fCanExport,canExport) && + GetBoolFromConfig(ConfigSection(),fMustProtectIfRecording,mustProtectIfRecording) && + GetBoolFromConfig(ConfigSection(),fCanPlay,canPlay) && + GetStringFromConfig(ConfigSection(),fContentId,contentId) && + GetStringFromConfig(ConfigSection(),fRightsIssuerUri,rightsIssuerUri)) + { + TExpectedKeyStreamDecoderAttributes newExpectedValues; + + newExpectedValues.IsProgramProtected = isProgramProtected; + newExpectedValues.IsServiceProtected = isServiceProtected; + newExpectedValues.CanExport = canExport; + newExpectedValues.MustProtectIfRecording = mustProtectIfRecording; + newExpectedValues.CanPlay = canPlay; + newExpectedValues.ContentId.Set(contentId); + newExpectedValues.RightsIssuerUri.Set(rightsIssuerUri); + + iExpectedKeyStreamDecoderData.Append(newExpectedValues); + + baseIndex++; + fIsProgramProtected.Format(KScafConfigIsProgramProtected,baseIndex); + fIsServiceProtected.Format(KScafConfigIsServiceProtected,baseIndex); + fCanExport.Format(KScafConfigCanExport,baseIndex); + fMustProtectIfRecording.Format(KScafConfigMustProtectIfRecording,baseIndex); + fCanPlay.Format(KScafConfigCanPlay,baseIndex); + fContentId.Format(KScafConfigContentId,baseIndex); + fRightsIssuerUri.Format(KScafConfigRightsIssuerUri,baseIndex); + } + + // Read OOM Test Flag + GetBoolFromConfig(ConfigSection(), KScafConfigOOMTest, iOOMTest); + } + +TBool CScafStep::CheckKeyStreamDecoderAttributesL(const CKeyStreamDecoder& aDecoder, + const TExpectedKeyStreamDecoderAttributes& aExpectedData) + { + // Overall result of the attribute value checks (ETrue = Pass / EFalse = Fail) + TBool result = ETrue; + + _LIT(KIsProgramProtectedDescription,"IsProgramProtected"); + _LIT(KIsServiceProtectedDescription,"IsServiceProtected"); + _LIT(KCanExportDescription,"CanExport"); + _LIT(KMustProtectIfRecordingDescription,"MustProtectIfRecording"); + _LIT(KCanPlayDescription,"CanPlay"); + _LIT(KContentIDDescription,"ContentID"); + _LIT(KRightIssuerURIDescription,"RightIssuerURI"); + + // Query the stream agent to determine whether the program is protected + if(!CompareBooleanAttributeL(aDecoder, + EIsProgramProtected, + KIsProgramProtectedDescription, + aExpectedData.IsProgramProtected)) + { + result = EFalse; + } + + // Query the stream agent to determine whether the whole service is protected + if(!CompareBooleanAttributeL(aDecoder, + EIsServiceProtected, + KIsServiceProtectedDescription, + aExpectedData.IsServiceProtected)) + { + result = EFalse; + } + + // Query the stream agent to determine whether the content can be exported + if(!CompareBooleanAttributeL(aDecoder, + ECanExport, + KCanExportDescription, + aExpectedData.CanExport)) + { + result = EFalse; + } + + // Query the stream agent to determine whether the content must be protected whilst recording + if(!CompareBooleanAttributeL(aDecoder, + EMustProtectIfRecording, + KMustProtectIfRecordingDescription, + aExpectedData.MustProtectIfRecording)) + { + result = EFalse; + } + + // Query the stream agent to determine whether the content can be played + if(!CompareBooleanAttributeL(aDecoder, + ECanPlay, + KCanPlayDescription, + aExpectedData.CanPlay)) + { + result = EFalse; + } + + // Query the stream agent to retrieve the Content ID + if(!CompareStringAttributeL(aDecoder, + EContentID, + KContentIDDescription, + aExpectedData.ContentId)) + { + result = EFalse; + } + + // Query the stream agent to retrieve the Rights Issuer URI + if(!CompareStringAttributeL(aDecoder, + ERightsIssuerURI, + KRightIssuerURIDescription, + aExpectedData.RightsIssuerUri)) + { + result = EFalse; + } + + return result; + } + +TBool CScafStep::CompareBooleanAttributeL(const CKeyStreamDecoder& aDecoder, + const TAttribute& aAttributeEnum, + const TDesC& aAttributeDescription, + const TBool aExpectedValue) + { + TBool retrievedValue; + + // Query the stream agent to determine the actual value of the attribute + TRAPD(err,aDecoder.GetAttributeL(aAttributeEnum,retrievedValue)); + + if(err != KErrNone) + { + ERR_PRINTF4(_L("*** Thread %d: Failed to Retrieve '%S' Value - %d ***"),iThreadId,&aAttributeDescription,err); + User::Leave(err); + } + + if(retrievedValue != aExpectedValue) + { + INFO_PRINTF4(_L("Thread %d: Expected '%S' Value = %d"),iThreadId,&aAttributeDescription,aExpectedValue); + INFO_PRINTF4(_L("Thread %d: Retrieved '%S' Value = %d"),iThreadId,&aAttributeDescription,retrievedValue); + ERR_PRINTF3(_L("*** Thread %d: Unexpected '%S' Value ***"),iThreadId,&aAttributeDescription); + return EFalse; + } + + return ETrue; + } + +TBool CScafStep::CompareStringAttributeL(const CKeyStreamDecoder& aDecoder, + const TStringAttribute& aAttributeEnum, + const TDesC& aAttributeDescription, + const TDesC& aExpectedValue) + { + TBool result = ETrue; + + // Query the stream agent to determine the actual value of the attribute + HBufC* retrievedValue = aDecoder.GetStringAttributeLC(aAttributeEnum); + + if(retrievedValue->Des() != aExpectedValue) + { + INFO_PRINTF4(_L("Thread %d: Expected '%S' Value = %S"),iThreadId,&aAttributeDescription,&aExpectedValue); + INFO_PRINTF4(_L("Thread %d: Retrieved '%S' Value = %S"),iThreadId,&aAttributeDescription,retrievedValue); + ERR_PRINTF3(_L("*** Thread %d: Unexpected '%S' Value ***"),iThreadId,&aAttributeDescription); + result = EFalse; + } + + // Destroy the heap based descriptor + CleanupStack::PopAndDestroy(retrievedValue); + + return result; + }