diff -r 641f389e9157 -r a71299154b21 authenticationservices/authenticationserver/test/tauthcliserv/step_authexpr_eval.cpp --- a/authenticationservices/authenticationserver/test/tauthcliserv/step_authexpr_eval.cpp Tue Aug 31 17:00:08 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,697 +0,0 @@ -/* -* Copyright (c) 2005-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: -* This file contains functions which are used to -* test evaluating authentication expressions. -* -*/ - - -#include "tauthcliservstep.h" - -using namespace AuthServer; - -typedef TTestPluginInterface::TCallEntry TCE; - -#define elemCount(___x) (sizeof(___x) / sizeof(___x[0])) - -static TAuthExpressionWrapper BuildLeftAnd(TInt aRemainingLevels); -static TAuthExpressionWrapper BuildRightAnd(TInt aRemainingLevels); -static TAuthExpressionWrapper BuildBalancedAnd(TInt aRemainingLevels); -static TAuthExpressionWrapper BuildFailedAnd(TInt aRemainingLevels); -static TAuthExpressionWrapper BuildSuccessfulOr(TInt aRemainingLevels); - - -// -------- CTStepActSch -------- - - -// -------- CTStepAuthExprEval -------- - - -void TTestPluginInterface::Evaluate(TPluginId aPluginId, TIdentityId& aIdentity, - CAuthExpressionImpl::TType /*aType*/, TRequestStatus& aStatus) -/** - Implement MEvaluatorPluginInterface by completing - the request with an identity equal to the plugin id. - */ - { - const TCallEntry ce(aPluginId); - TInt r = iCallLog.Append(ce); - - // this can be KErrNoMemory in OOM tests - if (r == KErrNone) - { - if (aPluginId == KTestPluginUnknown) - aIdentity = KUnknownIdentity; - else - aIdentity = static_cast(aPluginId); - } - - aStatus = KRequestPending; - TRequestStatus* rs = &aStatus; - User::RequestComplete(rs, r); - } - - -void TTestPluginInterface::Evaluate(TAuthPluginType aPluginType, TIdentityId& aIdentity, - CAuthExpressionImpl::TType /*aType*/, TRequestStatus& aStatus) -/** - Implement MEvaluatorPluginInterface by completing - the request with an identity equal to the plugin type. - */ - { - const TCallEntry ce(aPluginType); - TInt r = iCallLog.Append(ce); - - // this can be KerrNoMemory in OOM tests - if (r == KErrNone) - aIdentity = static_cast(aPluginType); - - aStatus = KRequestPending; - TRequestStatus* rs = &aStatus; - User::RequestComplete(rs, KErrNone); - } - - -bool TTestPluginInterface::TCallEntry::operator==(const TTestPluginInterface::TCallEntry& aRhs) const - { - if (iCallType != aRhs.iCallType) - return false; - - if (iCallType == CAuthExpressionImpl::EPluginId) - return iPluginId == aRhs.iPluginId; - else - return iPluginType == aRhs.iPluginType; - } - - -void TTestClientInterface::EvaluationSucceeded(TIdentityId aIdentityId) -/** - Implement MEvaluatorClientInterface by recording - that the evaluation succeeded, and the resulting identity. - */ - { - iMode = ESucceeded; - iIdentityId = aIdentityId; - - CActiveScheduler::Stop(); - } - - -void TTestClientInterface::EvaluationFailed(TInt aReason) -/** - Implement MEvaluatorClientInterface by recording - that the evaluation failed, and the failure reason. - */ - { - iMode = EFailed; - iReason = aReason; - - CActiveScheduler::Stop(); - } - - -CLaunchEval* CLaunchEval::NewL() -/** - Factory function allocates new instance of CLaunchEval. - - @return New instance of CLaunchEval. - */ - { - CLaunchEval* self = new(ELeave) CLaunchEval(); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(self); - return self; - } - - -CLaunchEval::CLaunchEval() -/** - Set timer priority and add self to active scheduler. - */ -: CActive(CActive::EPriorityStandard) - { - CActiveScheduler::Add(this); - } - - -void CLaunchEval::ConstructL() -/** - Allocate evaluator and initialize superclass timer. - */ - { -// CTimer::ConstructL(); - iEval = CEvaluator::NewL(&iPluginInterface, &iClientInterface); - } - - -CLaunchEval::~CLaunchEval() -/** - Deletes evaluator which was allocated for this object. - */ - { - ResetInterfaces(); - delete iEval; - } - - -void CLaunchEval::ResetInterfaces() -/** - Free resources used by plugin and client interfaces. - */ - { - iPluginInterface.iCallLog.Reset(); - iClientInterface.iMode = TTestClientInterface::ENone; - } - - -void CLaunchEval::Evaluate(const CAuthExpression* aExpr) -/** - Queue this timer object and start the active - scheduler. This function returns when the evaluation - has completed. - - This object's client and plugin interfaces are reset - before the expression is evaluated, so they can be - tested by the function which calls this. - - @param aExpr Expression to evaluate. - */ - { - ResetInterfaces(); - iExpr = aExpr; // store so can see in RunL - - // signal this object. This ensures there - // is a pending active object before the scheduler - // is started. - iStatus = KRequestPending; - TRequestStatus* rs = &iStatus; - User::RequestComplete(rs, KErrNone); - SetActive(); - - // block until the evaluation has completed. - CActiveScheduler::Start(); - } - - -void CLaunchEval::RunL() -/** - Implement CActive by launching the evaluation. - At this point the active scheduler should have - been started. - */ - { - iEval->Evaluate(static_cast(iExpr)); - } - - -void CLaunchEval::DoCancel() -/** - Implement CActive by cancelling the evaluation - which is currently in progress. - - Not yet implemented. - */ - { - // empty. - } - - -CTStepAuthExprEval::CTStepAuthExprEval() -/** - Record this test step's name. - */ - { - SetTestStepName(KTStepAuthExprTypePncBadRight); - } - - -TVerdict CTStepAuthExprEval::doTestStepL() - { - CActiveScheduler::Install(iActSchd); - User::SetJustInTime(ETrue); - - __UHEAP_MARK; - TestEvalCreateL(); - TestEvalSimpleL(); - TestEvalAndL(); - TestEvalOrL(); - TestRPNReallocL(); - __UHEAP_MARKEND; - - return EPass; - } - - -void CTStepAuthExprEval::TestEvalCreateL() -/** - Test allocating and deleting an evaluator, - without using it for anything. - */ - { - __UHEAP_MARK; - - TTestClientInterface tci; - TTestPluginInterface tpi; - - CEvaluator* ev = CEvaluator::NewL(&tpi, &tci); - delete ev; - - __UHEAP_MARKEND; - } - - -void CTStepAuthExprEval::TestEvalSimpleL() -/** - Test evaluating a simple plugin id, and - evaluating a simple plugin type. - */ - { - __UHEAP_MARK; - - CLaunchEval* le = CLaunchEval::NewL(); - CleanupStack::PushL(le); - - // simple plugin id - CAuthExpression* aeId = AuthExpr(KTestPluginId0); - User::LeaveIfNull(aeId); - le->Evaluate(aeId); - delete aeId; - - const TCE aceI0[] = {TCE(KTestPluginId0)}; - TestEvalResultL(le, KTestPluginId0, aceI0, elemCount(aceI0)); - - // simple plugin type - CAuthExpression* aeType = AuthExpr(EAuthBiometric); - User::LeaveIfNull(aeType); - le->Evaluate(aeType); - delete aeType; - - const TCE aceTB[] = {TCE(EAuthBiometric)}; - TestEvalResultL(le, EAuthBiometric, aceTB, elemCount(aceTB)); - - CleanupStack::PopAndDestroy(le); - - __UHEAP_MARKEND; - } - - -void CTStepAuthExprEval::TestEvalAndL() -/** - Test evaluating simple AND expressions. - */ - { - __UHEAP_MARK; - - CLaunchEval* le = CLaunchEval::NewL(); - CleanupStack::PushL(le); - - // U & U = U (sc) - CAuthExpression* aeUU = AuthAnd(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginUnknown)); - User::LeaveIfNull(aeUU); - le->Evaluate(aeUU); - delete aeUU; - - const TCE aceUU[] = {TCE(KTestPluginUnknown)}; - TestEvalResultL(le, KUnknownIdentity, aceUU, elemCount(aceUU)); - - // U & I1 = U (sc) - CAuthExpression* aeUI1 = AuthAnd(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginId1)); - User::LeaveIfNull(aeUI1); - le->Evaluate(aeUI1); - delete aeUI1; - - const TCE aceUI1[] = {TCE(KTestPluginUnknown)}; - TestEvalResultL(le, KUnknownIdentity, aceUI1, elemCount(aceUI1)); - - // I1 & U = U - CAuthExpression* aeI1U = AuthAnd(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginUnknown)); - User::LeaveIfNull(aeI1U); - le->Evaluate(aeI1U); - delete aeI1U; - - const TCE aceI1U[] = {TCE(KTestPluginId1), TCE(KTestPluginUnknown)}; - TestEvalResultL(le, KUnknownIdentity, aceI1U, elemCount(aceI1U)); - - // I1 & I1 = I1 - CAuthExpression* aeI1I1 = AuthAnd(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId1)); - User::LeaveIfNull(aeI1I1); - le->Evaluate(aeI1I1); - delete aeI1I1; - - const TCE aceI1I1[] = {TCE(KTestPluginId1), TCE(KTestPluginId1)}; - TestEvalResultL(le, KTestPluginId1, aceI1I1, elemCount(aceI1I1)); - - // I1 & I2 = U - CAuthExpression* aeI1I2 = AuthAnd(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId2)); - User::LeaveIfNull(aeI1I2); - le->Evaluate(aeI1I2); - delete aeI1I2; - - const TCE aceI1I2[] = {TCE(KTestPluginId1), TCE(KTestPluginId2)}; - TestEvalResultL(le, KUnknownIdentity, aceI1I2, elemCount(aceI1I2)); - - CleanupStack::PopAndDestroy(le); - - __UHEAP_MARKEND; - } - - -void CTStepAuthExprEval::TestEvalOrL() -/** - Test evaluating simple OR expressions. - */ - { - __UHEAP_MARK; - - CLaunchEval* le = CLaunchEval::NewL(); - CleanupStack::PushL(le); - - // U | U = U - CAuthExpression* aeUU = AuthOr(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginUnknown)); - User::LeaveIfNull(aeUU); - le->Evaluate(aeUU); - delete aeUU; - - const TCE aceUU[] = {TCE(KTestPluginUnknown), TCE(KTestPluginUnknown)}; - TestEvalResultL(le, KUnknownIdentity, aceUU, elemCount(aceUU)); - - // U | I1 = I1 - CAuthExpression* aeUI1 = AuthOr(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginId1)); - User::LeaveIfNull(aeUI1); - le->Evaluate(aeUI1); - delete aeUI1; - - const TCE aceUI1[] = {TCE(KTestPluginUnknown), TCE(KTestPluginId1)}; - TestEvalResultL(le, KTestPluginId1, aceUI1, elemCount(aceUI1)); - - // I1 | U = I1 (sc) - CAuthExpression* aeI1U = AuthOr(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginUnknown)); - User::LeaveIfNull(aeI1U); - le->Evaluate(aeI1U); - delete aeI1U; - - const TCE aceI1U[] = {TCE(KTestPluginId1)}; - TestEvalResultL(le, KTestPluginId1, aceI1U, elemCount(aceI1U)); - - // I1 | I1 = I1 (sc) - CAuthExpression* aeI1I1 = AuthOr(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId1)); - User::LeaveIfNull(aeI1I1); - le->Evaluate(aeI1I1); - delete aeI1I1; - - const TCE aceI1I1[] = {TCE(KTestPluginId1)}; - TestEvalResultL(le, KTestPluginId1, aceI1I1, elemCount(aceI1I1)); - - // I1 | I2 = I1 (sc) - CAuthExpression* aeI1I2 = AuthOr(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId2)); - User::LeaveIfNull(aeI1I2); - le->Evaluate(aeI1I2); - delete aeI1I2; - - const TCE aceI1I2[] = {TCE(KTestPluginId1)}; - TestEvalResultL(le, KTestPluginId1, aceI1I2, elemCount(aceI1I2)); - - CleanupStack::PopAndDestroy(le); - - __UHEAP_MARKEND; - } - - -void CTStepAuthExprEval::TestEvalResultL( - CLaunchEval* aLaunchEval, TIdentityId aIdentityId, - const TTestPluginInterface::TCallEntry* aExpEntries, TInt aEntryCount) -/** - Test the evaluation produced the expected result, and - that the expected plugins were called in the right order. - */ - { - const TTestClientInterface& cli = aLaunchEval->iClientInterface; - TESTL(cli.iMode == TTestClientInterface::ESucceeded); - TESTL(cli.iIdentityId == aIdentityId); - - const RArray& log = aLaunchEval->iPluginInterface.iCallLog; - - TESTL(log.Count() == aEntryCount); - for (TInt i = 0; i < aEntryCount; ++i) - { - TESTL(log[i] == aExpEntries[i]); - } - } - - -static TAuthExpressionWrapper BuildLeftAnd(TInt aRemainingLevels) -/** - Build an expression where the left side is an - AND expression and the right side is a plugin ID. - - @param aRemainingLevels The number of layers to build - below this layer. If - aRemainingLevels == 0 this function - returns a simple plugin ID expression. - */ - { - return (aRemainingLevels == 0) - ? AuthExpr(KTestPluginId1) - : AuthAnd(BuildLeftAnd(aRemainingLevels - 1), AuthExpr(KTestPluginId1)); - } - - -static TAuthExpressionWrapper BuildRightAnd(TInt aRemainingLevels) -/** - Build an expression where the left side is a - plugin ID and the right side is an AND expression. - - @param aRemainingLevels The number of layers to build - below this layer. If - aRemainingLevels == 0 this function - returns a simple plugin ID expression. - */ - { - return (aRemainingLevels == 0) - ? AuthExpr(KTestPluginId1) - : AuthAnd(AuthExpr(KTestPluginId1), BuildRightAnd(aRemainingLevels - 1)); - } - - -static TAuthExpressionWrapper BuildBalancedAnd(TInt aRemainingLevels) -/** - Build an expression where both the left and right side - have the same depth, aRemainingLevels - 1. - - @param aRemainingLevels The number of layers to build - below this layer. If - aRemainingLevels == 0 this function - returns a simple plugin ID expression. - */ - { - return (aRemainingLevels == 0) - ? AuthExpr(KTestPluginId1) - : AuthAnd( - BuildBalancedAnd(aRemainingLevels - 1), - BuildBalancedAnd(aRemainingLevels - 1)); - } - - -static TAuthExpressionWrapper BuildFailedAnd(TInt aRemainingLevels) -/** - This function creates an expression where the left node - is a simple plugin ID expression and the right node is - built recursively with this function. The final AND node - has a left unknown plugin ID. - - This causes an unknown plugin ID to be automatically pushed - onto the RPN stack as a right value before the compounder is used. - - @param aRemainingLevels Number of levels to generate after this. - If aRemainingLevels == 1 this function - creates an AND node where the left node - is unknown. Otherwise it generates an - AND node where the left node is a known - plugin ID and the right node is generated - recursively. - */ - { - return (aRemainingLevels == 1) - ? AuthAnd(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginId1)) - : AuthAnd(AuthExpr(KTestPluginId1), BuildFailedAnd(aRemainingLevels - 1)); - } - - -static TAuthExpressionWrapper BuildSuccessfulOr(TInt aRemainingLevels) -/** - This function creates an AND node where the left node - is a known plugin ID, and the right right node is generated - recursively. This creates a right-descent list, but the - penultimate node is an OR expression whose left node is a - known plugin ID. - - This puts a series of known plugin IDs on the RPN stack from - the left nodes of the AND nodes. When the OR node is evaluated - the left node is known, and so automatically put on the - RPN stack. - - This means that an OR right node is automatically put on the - RPN stack at a known point, which is used to stress test failing - to append an OR right expression in OOM. - - @param aRemainingLevels Number of levels to generate after this. - If aRemainingLevels == 1 this function - generates an OR node. Otherwise it creates - and AND node as described above. - */ - { - return (aRemainingLevels == 1) - ? AuthOr(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId1)) - : AuthAnd(AuthExpr(KTestPluginId1), BuildSuccessfulOr(aRemainingLevels - 1)); - } - - -void CTStepAuthExprEval::TestRPNReallocL() -/** - Create a deeply nested expression which is - deep enough that the evaluator has to reallocate - its RPN stack, and checks the evaluation fails - gracefully in OOM. - */ - { - __UHEAP_MARK; - - RunOomTestsL(BuildLeftAnd, KTestPluginId1, 0); - RunOomTestsL(BuildRightAnd, KTestPluginId1, 0); - RunOomTestsL(BuildBalancedAnd, KTestPluginId1, 0); - RunOomTestsL(BuildFailedAnd, KUnknownIdentity, 1); - RunOomTestsL(BuildSuccessfulOr, KTestPluginId1, 1); - - __UHEAP_MARKEND; - } - - -void CTStepAuthExprEval::RunOomTestsL( - TAuthExpressionWrapper (*aAllocator)(TInt), - TIdentityId aExpectedIdentity, TInt aInitDepth) -/** - Attempt to evaluate the supplied expresision in OOM. - - Running in OOM will both fail the evaluation, when the - plugin interface attempts to append to the call log, and - when the evaluator attempts to extend the RPN stack. - - OOM can only be tested in debug builds. In release builds, - this function evaluates the expression at each depth and - tests the evaluator produces the correct result. - - @param aAllocator Function which allocates the expression. - @param aExpectedIdentity Identity which should be returned on - successful evaluation. - @param aInitDepth Initial depth. - */ - { - CLaunchEval* le = CLaunchEval::NewL(); - User::LeaveIfNull(le); - CleanupStack::PushL(le); - - const volatile TTestClientInterface& cli = le->iClientInterface; - - // depth starts at zero because, even though RPN stack - // is not used, the evaluator will attempt to grow its - // call log, and so fail the evaluation. (This test is - // therefore also used to test failed plugin evaluations.) - - // max depth is 13 because CStepControl::StartL creates - // a worker thread with a 1MB maximum heap. The - // number of allocated node cells for a balanced tree - // is 2^(depth+1) - 1. When depth==13, there are - // 16383 cells using 327,672 bytes excluding cell headers. - // Allocation fails for depth == 14. - - const TInt KMaxDepth = 13; - for (TInt depth = aInitDepth; depth <= KMaxDepth; ++depth) - { - CAuthExpression* ae = aAllocator(depth); - User::LeaveIfNull(ae); - CleanupStack::PushL(ae); - - // OOM testing only available in debug builds -#ifndef _DEBUG - le->Evaluate(ae); - TESTL(cli.iMode == TTestClientInterface::ESucceeded); - TESTL(cli.iIdentityId == aExpectedIdentity); -#else - TInt i = 0; - do - { - // Ideally, the heap would be marked before and - // after the evaluation. However, CEvaluator uses - // an CArrayFixFlat to store the RPN stack. - // When the first item is inserted, it allocates a - // CBufBase object to hold the data. This object - // is reset but not deleted when the RPN stack is - // reset, so there will be a heap imbalance of one - // if anything was added to the RPN stack, even though - // the stack is reset. - - TInt preSize; - TInt preCount = User::AllocSize(preSize); -// __UHEAP_MARK; - - __UHEAP_SETFAIL(RAllocator::EDeterministic, i); - le->Evaluate(ae); - __UHEAP_RESET; - - TESTL( cli.iMode == TTestClientInterface::EFailed - || cli.iMode == TTestClientInterface::ESucceeded); - - if (cli.iMode == TTestClientInterface::EFailed) - { - TESTL(cli.iReason == KErrNoMemory); - } - else - { - TESTL(cli.iIdentityId == aExpectedIdentity); - } - - // clear call log so heap checking will work - le->iPluginInterface.iCallLog.Reset(); - ++i; - - TInt postSize; - TInt postCount = User::AllocSize(postSize); - TESTL(postCount == preCount || postCount == preCount + 1); -// __UHEAP_MARKEND; - } while (cli.iMode != TTestClientInterface::ESucceeded); - - // test evaluation still succeeds and failed allocation - // was not ignored - TInt limit = 2 * i; - while (i++ < limit) - { - __UHEAP_SETFAIL(RAllocator::EDeterministic, i++); - le->Evaluate(ae); - __UHEAP_RESET; - - TESTL(cli.iMode == TTestClientInterface::ESucceeded); - TESTL(cli.iIdentityId == aExpectedIdentity); - } - - // clear plugin call log to reset mem usage for next iteration. - le->iPluginInterface.iCallLog.Reset(); -#endif // #else #ifndef _DEBUG - CleanupStack::PopAndDestroy(ae); - } - - CleanupStack::PopAndDestroy(le); - } -