authenticationservices/authenticationserver/test/tauthcliserv/step_authexpr_eval.cpp
changeset 102 deec7e509f66
parent 94 0e6c5a9328b5
child 108 ca9a0fc2f082
equal deleted inserted replaced
94:0e6c5a9328b5 102:deec7e509f66
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * This file contains functions which are used to
       
    16 * test evaluating authentication expressions.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 #include "tauthcliservstep.h"
       
    22 
       
    23 using namespace AuthServer;
       
    24 
       
    25 typedef TTestPluginInterface::TCallEntry TCE;
       
    26 
       
    27 #define elemCount(___x)		(sizeof(___x) / sizeof(___x[0]))
       
    28 
       
    29 static TAuthExpressionWrapper BuildLeftAnd(TInt aRemainingLevels);
       
    30 static TAuthExpressionWrapper BuildRightAnd(TInt aRemainingLevels);
       
    31 static TAuthExpressionWrapper BuildBalancedAnd(TInt aRemainingLevels);
       
    32 static TAuthExpressionWrapper BuildFailedAnd(TInt aRemainingLevels);
       
    33 static TAuthExpressionWrapper BuildSuccessfulOr(TInt aRemainingLevels);
       
    34 
       
    35 
       
    36 // -------- CTStepActSch --------
       
    37 
       
    38 
       
    39 // -------- CTStepAuthExprEval --------
       
    40 
       
    41 
       
    42 void TTestPluginInterface::Evaluate(TPluginId aPluginId, TIdentityId& aIdentity,
       
    43 		   CAuthExpressionImpl::TType /*aType*/, TRequestStatus& aStatus)
       
    44 /**
       
    45 	Implement MEvaluatorPluginInterface by completing
       
    46 	the request with an identity equal to the plugin id.
       
    47  */
       
    48 	{
       
    49 	const TCallEntry ce(aPluginId);
       
    50 	TInt r = iCallLog.Append(ce);
       
    51 	
       
    52 	// this can be KErrNoMemory in OOM tests
       
    53 	if (r == KErrNone)
       
    54 		{
       
    55 		if (aPluginId == KTestPluginUnknown)
       
    56 			aIdentity = KUnknownIdentity;
       
    57 		else
       
    58 			aIdentity = static_cast<TIdentityId>(aPluginId);
       
    59 		}
       
    60 		
       
    61 	aStatus = KRequestPending;
       
    62 	TRequestStatus* rs = &aStatus;
       
    63 	User::RequestComplete(rs, r);
       
    64 	}
       
    65 
       
    66 
       
    67 void TTestPluginInterface::Evaluate(TAuthPluginType aPluginType, TIdentityId& aIdentity, 
       
    68 									CAuthExpressionImpl::TType /*aType*/, TRequestStatus& aStatus)
       
    69 /**
       
    70 	Implement MEvaluatorPluginInterface by completing
       
    71 	the request with an identity equal to the plugin type.
       
    72  */
       
    73 	{
       
    74 	const TCallEntry ce(aPluginType);
       
    75 	TInt r = iCallLog.Append(ce);
       
    76 	
       
    77 	// this can be KerrNoMemory in OOM tests
       
    78 	if (r == KErrNone)
       
    79 		aIdentity = static_cast<TIdentityId>(aPluginType);
       
    80 	
       
    81 	aStatus = KRequestPending;
       
    82 	TRequestStatus* rs = &aStatus;
       
    83 	User::RequestComplete(rs, KErrNone);
       
    84 	}
       
    85 
       
    86 
       
    87 bool TTestPluginInterface::TCallEntry::operator==(const TTestPluginInterface::TCallEntry& aRhs) const
       
    88 	{
       
    89 	if (iCallType != aRhs.iCallType)
       
    90 		return false;
       
    91 	
       
    92 	if (iCallType == CAuthExpressionImpl::EPluginId)
       
    93 		return iPluginId == aRhs.iPluginId;
       
    94 	else
       
    95 		return iPluginType == aRhs.iPluginType;
       
    96 	}
       
    97 
       
    98 
       
    99 void TTestClientInterface::EvaluationSucceeded(TIdentityId aIdentityId)
       
   100 /**
       
   101 	Implement MEvaluatorClientInterface by recording
       
   102 	that the evaluation succeeded, and the resulting identity.
       
   103  */
       
   104 	{
       
   105 	iMode = ESucceeded;
       
   106 	iIdentityId = aIdentityId;
       
   107 
       
   108 	CActiveScheduler::Stop();
       
   109 	}
       
   110 
       
   111 
       
   112 void TTestClientInterface::EvaluationFailed(TInt aReason)
       
   113 /**
       
   114 	Implement MEvaluatorClientInterface by recording
       
   115 	that the evaluation failed, and the failure reason.
       
   116  */
       
   117 	{
       
   118 	iMode = EFailed;
       
   119 	iReason = aReason;
       
   120 	
       
   121 	CActiveScheduler::Stop();
       
   122 	}
       
   123 
       
   124 
       
   125 CLaunchEval* CLaunchEval::NewL()
       
   126 /**
       
   127 	Factory function allocates new instance of CLaunchEval.
       
   128 	
       
   129 	@return					New instance of CLaunchEval.
       
   130  */
       
   131 	{
       
   132 	CLaunchEval* self = new(ELeave) CLaunchEval();
       
   133 	CleanupStack::PushL(self);
       
   134 	self->ConstructL();
       
   135 	CleanupStack::Pop(self);
       
   136 	return self;
       
   137 	}
       
   138 
       
   139 
       
   140 CLaunchEval::CLaunchEval()
       
   141 /**
       
   142 	Set timer priority and add self to active scheduler.
       
   143  */
       
   144 :	CActive(CActive::EPriorityStandard)
       
   145 	{
       
   146 	CActiveScheduler::Add(this);
       
   147 	}
       
   148 
       
   149 
       
   150 void CLaunchEval::ConstructL()
       
   151 /**
       
   152 	Allocate evaluator and initialize superclass timer.
       
   153  */
       
   154 	{
       
   155 //	CTimer::ConstructL();
       
   156 	iEval = CEvaluator::NewL(&iPluginInterface, &iClientInterface);
       
   157 	}
       
   158 
       
   159 
       
   160 CLaunchEval::~CLaunchEval()
       
   161 /**
       
   162 	Deletes evaluator which was allocated for this object.
       
   163  */
       
   164 	{
       
   165 	ResetInterfaces();
       
   166 	delete iEval;
       
   167 	}
       
   168 
       
   169 
       
   170 void CLaunchEval::ResetInterfaces()
       
   171 /**
       
   172 	Free resources used by plugin and client interfaces.
       
   173  */
       
   174 	{
       
   175 	iPluginInterface.iCallLog.Reset();
       
   176 	iClientInterface.iMode = TTestClientInterface::ENone;
       
   177 	}
       
   178 
       
   179 
       
   180 void CLaunchEval::Evaluate(const CAuthExpression* aExpr)
       
   181 /**
       
   182 	Queue this timer object and start the active
       
   183 	scheduler.  This function returns when the evaluation
       
   184 	has completed.
       
   185 	
       
   186 	This object's client and plugin interfaces are reset
       
   187 	before the expression is evaluated, so they can be
       
   188 	tested by the function which calls this.
       
   189 	
       
   190 	@param	aExpr			Expression to evaluate.
       
   191  */
       
   192 	{
       
   193 	ResetInterfaces();
       
   194 	iExpr = aExpr;			// store so can see in RunL
       
   195 	
       
   196 	// signal this object.  This ensures there
       
   197 	// is a pending active object before the scheduler
       
   198 	// is started.
       
   199 	iStatus = KRequestPending;
       
   200 	TRequestStatus* rs = &iStatus;
       
   201 	User::RequestComplete(rs, KErrNone);
       
   202 	SetActive();
       
   203 	
       
   204 	// block until the evaluation has completed.
       
   205 	CActiveScheduler::Start();
       
   206 	}
       
   207 
       
   208 
       
   209 void CLaunchEval::RunL()
       
   210 /**
       
   211 	Implement CActive by launching the evaluation.
       
   212 	At this point the active scheduler should have
       
   213 	been started.
       
   214  */
       
   215 	{
       
   216 	iEval->Evaluate(static_cast<const CAuthExpressionImpl*>(iExpr));
       
   217 	}
       
   218 
       
   219 
       
   220 void CLaunchEval::DoCancel()
       
   221 /**
       
   222 	Implement CActive by cancelling the evaluation
       
   223 	which is currently in progress.
       
   224 	
       
   225 	Not yet implemented.
       
   226  */
       
   227 	{
       
   228 	// empty.
       
   229 	}
       
   230 
       
   231 
       
   232 CTStepAuthExprEval::CTStepAuthExprEval()
       
   233 /**
       
   234 	Record this test step's name.
       
   235  */
       
   236 	{
       
   237 	SetTestStepName(KTStepAuthExprTypePncBadRight);
       
   238 	}
       
   239 
       
   240 
       
   241 TVerdict CTStepAuthExprEval::doTestStepL()
       
   242 	{
       
   243  	CActiveScheduler::Install(iActSchd);
       
   244  	User::SetJustInTime(ETrue);
       
   245  	
       
   246  	__UHEAP_MARK;
       
   247 	TestEvalCreateL();
       
   248 	TestEvalSimpleL();
       
   249 	TestEvalAndL();
       
   250 	TestEvalOrL();
       
   251 	TestRPNReallocL();
       
   252 	__UHEAP_MARKEND;
       
   253 	
       
   254 	return EPass;
       
   255 	}
       
   256 
       
   257 
       
   258 void CTStepAuthExprEval::TestEvalCreateL()
       
   259 /**
       
   260 	Test allocating and deleting an evaluator,
       
   261 	without using it for anything.
       
   262  */
       
   263 	{
       
   264 	__UHEAP_MARK;
       
   265 	
       
   266 	TTestClientInterface tci;
       
   267 	TTestPluginInterface tpi;
       
   268 	
       
   269 	CEvaluator* ev = CEvaluator::NewL(&tpi, &tci);
       
   270 	delete ev;
       
   271 	
       
   272 	__UHEAP_MARKEND;
       
   273 	}
       
   274 
       
   275 
       
   276 void CTStepAuthExprEval::TestEvalSimpleL()
       
   277 /**
       
   278 	Test evaluating a simple plugin id, and
       
   279 	evaluating a simple plugin type.
       
   280  */
       
   281 	{
       
   282 	__UHEAP_MARK;
       
   283 	
       
   284 	CLaunchEval* le = CLaunchEval::NewL();
       
   285 	CleanupStack::PushL(le);
       
   286 
       
   287 	// simple plugin id	
       
   288 	CAuthExpression* aeId = AuthExpr(KTestPluginId0);
       
   289 	User::LeaveIfNull(aeId);
       
   290 	le->Evaluate(aeId);
       
   291 	delete aeId;
       
   292 	
       
   293 	const TCE aceI0[] = {TCE(KTestPluginId0)};
       
   294 	TestEvalResultL(le, KTestPluginId0, aceI0, elemCount(aceI0));
       
   295 	
       
   296 	// simple plugin type
       
   297 	CAuthExpression* aeType = AuthExpr(EAuthBiometric);
       
   298 	User::LeaveIfNull(aeType);
       
   299 	le->Evaluate(aeType);
       
   300 	delete aeType;
       
   301 	
       
   302 	const TCE aceTB[] = {TCE(EAuthBiometric)};
       
   303 	TestEvalResultL(le, EAuthBiometric, aceTB, elemCount(aceTB));
       
   304 	
       
   305 	CleanupStack::PopAndDestroy(le);
       
   306 	
       
   307 	__UHEAP_MARKEND;
       
   308 	}
       
   309 
       
   310 
       
   311 void CTStepAuthExprEval::TestEvalAndL()
       
   312 /**
       
   313 	Test evaluating simple AND expressions.
       
   314  */
       
   315 	{
       
   316 	__UHEAP_MARK;
       
   317 	
       
   318 	CLaunchEval* le = CLaunchEval::NewL();
       
   319 	CleanupStack::PushL(le);
       
   320 
       
   321 	// U & U = U (sc)
       
   322 	CAuthExpression* aeUU = AuthAnd(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginUnknown));
       
   323 	User::LeaveIfNull(aeUU);
       
   324 	le->Evaluate(aeUU);
       
   325 	delete aeUU;
       
   326 
       
   327 	const TCE aceUU[] = {TCE(KTestPluginUnknown)};
       
   328 	TestEvalResultL(le, KUnknownIdentity, aceUU, elemCount(aceUU));
       
   329 
       
   330 	// U & I1 = U (sc)
       
   331 	CAuthExpression* aeUI1 = AuthAnd(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginId1));
       
   332 	User::LeaveIfNull(aeUI1);
       
   333 	le->Evaluate(aeUI1);
       
   334 	delete aeUI1;
       
   335 	
       
   336 	const TCE aceUI1[] = {TCE(KTestPluginUnknown)};
       
   337 	TestEvalResultL(le, KUnknownIdentity, aceUI1, elemCount(aceUI1));
       
   338 	
       
   339 	// I1 & U = U
       
   340 	CAuthExpression* aeI1U = AuthAnd(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginUnknown));
       
   341 	User::LeaveIfNull(aeI1U);
       
   342 	le->Evaluate(aeI1U);
       
   343 	delete aeI1U;
       
   344 
       
   345 	const TCE aceI1U[] = {TCE(KTestPluginId1), TCE(KTestPluginUnknown)};
       
   346 	TestEvalResultL(le, KUnknownIdentity, aceI1U, elemCount(aceI1U));
       
   347 	
       
   348 	// I1 & I1 = I1
       
   349 	CAuthExpression* aeI1I1 = AuthAnd(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId1));
       
   350 	User::LeaveIfNull(aeI1I1);
       
   351 	le->Evaluate(aeI1I1);
       
   352 	delete aeI1I1;
       
   353 
       
   354 	const TCE aceI1I1[] = {TCE(KTestPluginId1), TCE(KTestPluginId1)};
       
   355 	TestEvalResultL(le, KTestPluginId1, aceI1I1, elemCount(aceI1I1));
       
   356 	
       
   357 	// I1 & I2 = U
       
   358 	CAuthExpression* aeI1I2 = AuthAnd(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId2));
       
   359 	User::LeaveIfNull(aeI1I2);
       
   360 	le->Evaluate(aeI1I2);
       
   361 	delete aeI1I2;
       
   362 	
       
   363 	const TCE aceI1I2[] = {TCE(KTestPluginId1), TCE(KTestPluginId2)};
       
   364 	TestEvalResultL(le, KUnknownIdentity, aceI1I2, elemCount(aceI1I2));
       
   365 	
       
   366 	CleanupStack::PopAndDestroy(le);
       
   367 	
       
   368 	__UHEAP_MARKEND;
       
   369 	}
       
   370 
       
   371 
       
   372 void CTStepAuthExprEval::TestEvalOrL()
       
   373 /**
       
   374 	Test evaluating simple OR expressions.
       
   375  */
       
   376 	{
       
   377 	__UHEAP_MARK;
       
   378 	
       
   379 	CLaunchEval* le = CLaunchEval::NewL();
       
   380 	CleanupStack::PushL(le);
       
   381 
       
   382 	// U | U = U
       
   383 	CAuthExpression* aeUU = AuthOr(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginUnknown));
       
   384 	User::LeaveIfNull(aeUU);
       
   385 	le->Evaluate(aeUU);
       
   386 	delete aeUU;
       
   387 	
       
   388 	const TCE aceUU[] = {TCE(KTestPluginUnknown), TCE(KTestPluginUnknown)};
       
   389 	TestEvalResultL(le, KUnknownIdentity, aceUU, elemCount(aceUU));
       
   390 	
       
   391 	// U | I1 = I1
       
   392 	CAuthExpression* aeUI1 = AuthOr(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginId1));
       
   393 	User::LeaveIfNull(aeUI1);
       
   394 	le->Evaluate(aeUI1);
       
   395 	delete aeUI1;
       
   396 	
       
   397 	const TCE aceUI1[] = {TCE(KTestPluginUnknown), TCE(KTestPluginId1)};
       
   398 	TestEvalResultL(le, KTestPluginId1, aceUI1, elemCount(aceUI1));
       
   399 	
       
   400 	// I1 | U = I1 (sc)
       
   401 	CAuthExpression* aeI1U = AuthOr(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginUnknown));
       
   402 	User::LeaveIfNull(aeI1U);
       
   403 	le->Evaluate(aeI1U);
       
   404 	delete aeI1U;
       
   405 	
       
   406 	const TCE aceI1U[] = {TCE(KTestPluginId1)};
       
   407 	TestEvalResultL(le, KTestPluginId1, aceI1U, elemCount(aceI1U));
       
   408 	
       
   409 	// I1 | I1 = I1 (sc)
       
   410 	CAuthExpression* aeI1I1 = AuthOr(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId1));
       
   411 	User::LeaveIfNull(aeI1I1);
       
   412 	le->Evaluate(aeI1I1);
       
   413 	delete aeI1I1;
       
   414 	
       
   415 	const TCE aceI1I1[] = {TCE(KTestPluginId1)};
       
   416 	TestEvalResultL(le, KTestPluginId1, aceI1I1, elemCount(aceI1I1));
       
   417 	
       
   418 	// I1 | I2 = I1 (sc)
       
   419 	CAuthExpression* aeI1I2 = AuthOr(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId2));
       
   420 	User::LeaveIfNull(aeI1I2);
       
   421 	le->Evaluate(aeI1I2);
       
   422 	delete aeI1I2;
       
   423 	
       
   424 	const TCE aceI1I2[] = {TCE(KTestPluginId1)};
       
   425 	TestEvalResultL(le, KTestPluginId1, aceI1I2, elemCount(aceI1I2));
       
   426 	
       
   427 	CleanupStack::PopAndDestroy(le);
       
   428 	
       
   429 	__UHEAP_MARKEND;
       
   430 	}
       
   431 
       
   432 
       
   433 void CTStepAuthExprEval::TestEvalResultL(
       
   434 	CLaunchEval* aLaunchEval, TIdentityId aIdentityId,
       
   435 	const TTestPluginInterface::TCallEntry* aExpEntries, TInt aEntryCount)
       
   436 /**
       
   437 	Test the evaluation produced the expected result, and
       
   438 	that the expected plugins were called in the right order.
       
   439  */
       
   440 	{
       
   441 	const TTestClientInterface& cli = aLaunchEval->iClientInterface;
       
   442 	TESTL(cli.iMode == TTestClientInterface::ESucceeded);
       
   443 	TESTL(cli.iIdentityId == aIdentityId);
       
   444 	
       
   445 	const RArray<TCE>& log = aLaunchEval->iPluginInterface.iCallLog;
       
   446 	
       
   447 	TESTL(log.Count() == aEntryCount);
       
   448 	for (TInt i = 0; i < aEntryCount; ++i)
       
   449 		{
       
   450 		TESTL(log[i] == aExpEntries[i]);
       
   451 		}
       
   452 	}
       
   453 
       
   454 
       
   455 static TAuthExpressionWrapper BuildLeftAnd(TInt aRemainingLevels)
       
   456 /**
       
   457 	Build an expression where the left side is an
       
   458 	AND expression and the right side is a plugin ID.
       
   459 	
       
   460 	@param	aRemainingLevels The number of layers to build
       
   461 							below this layer.  If
       
   462 							aRemainingLevels == 0 this function
       
   463 							returns a simple plugin ID expression.
       
   464  */
       
   465 	{
       
   466 	return (aRemainingLevels == 0)
       
   467 		?	AuthExpr(KTestPluginId1)
       
   468 		:	AuthAnd(BuildLeftAnd(aRemainingLevels - 1), AuthExpr(KTestPluginId1));
       
   469 	}
       
   470 
       
   471 
       
   472 static TAuthExpressionWrapper BuildRightAnd(TInt aRemainingLevels)
       
   473 /**
       
   474 	Build an expression where the left side is a
       
   475 	plugin ID and the right side is an AND expression.
       
   476 
       
   477 	@param	aRemainingLevels The number of layers to build
       
   478 							below this layer.  If
       
   479 							aRemainingLevels == 0 this function
       
   480 							returns a simple plugin ID expression.
       
   481  */
       
   482 	{
       
   483 	return (aRemainingLevels == 0)
       
   484 		?	AuthExpr(KTestPluginId1)
       
   485 		:	AuthAnd(AuthExpr(KTestPluginId1), BuildRightAnd(aRemainingLevels - 1));
       
   486 	}
       
   487 
       
   488 
       
   489 static TAuthExpressionWrapper BuildBalancedAnd(TInt aRemainingLevels)
       
   490 /**
       
   491 	Build an expression where both the left and right side
       
   492 	have the same depth, aRemainingLevels - 1.
       
   493 	
       
   494 	@param	aRemainingLevels The number of layers to build
       
   495 							below this layer.  If
       
   496 							aRemainingLevels == 0 this function
       
   497 							returns a simple plugin ID expression.
       
   498  */
       
   499 	{
       
   500 	return (aRemainingLevels == 0)
       
   501 		?	AuthExpr(KTestPluginId1)
       
   502 		:	AuthAnd(
       
   503 				BuildBalancedAnd(aRemainingLevels - 1),
       
   504 				BuildBalancedAnd(aRemainingLevels - 1));
       
   505 	}
       
   506 
       
   507 
       
   508 static TAuthExpressionWrapper BuildFailedAnd(TInt aRemainingLevels)
       
   509 /**
       
   510 	This function creates an expression where the left node
       
   511 	is a simple plugin ID expression and the right node is
       
   512 	built recursively with this function.  The final AND node
       
   513 	has a left unknown plugin ID.
       
   514 	
       
   515 	This causes an unknown plugin ID to be automatically pushed
       
   516 	onto the RPN stack as a right value before the compounder is used.
       
   517 	
       
   518 	@param	aRemainingLevels Number of levels to generate after this.
       
   519 							If aRemainingLevels == 1 this function
       
   520 							creates an AND node where the left node
       
   521 							is unknown.  Otherwise it generates an
       
   522 							AND node where the left node is a known
       
   523 							plugin ID and the right node is generated
       
   524 							recursively.
       
   525  */
       
   526 	{
       
   527 	return (aRemainingLevels == 1)
       
   528 		?	AuthAnd(AuthExpr(KTestPluginUnknown), AuthExpr(KTestPluginId1))
       
   529 		:	AuthAnd(AuthExpr(KTestPluginId1), BuildFailedAnd(aRemainingLevels - 1));
       
   530 	}
       
   531 
       
   532 
       
   533 static TAuthExpressionWrapper BuildSuccessfulOr(TInt aRemainingLevels)
       
   534 /**
       
   535 	This function creates an AND node where the left node
       
   536 	is a known plugin ID, and the right right node is generated
       
   537 	recursively.  This creates a right-descent list, but the
       
   538 	penultimate node is an OR expression whose left node is a
       
   539 	known plugin ID.
       
   540 	
       
   541 	This puts a series of known plugin IDs on the RPN stack from
       
   542 	the left nodes of the AND nodes.  When the OR node is evaluated
       
   543 	the left node is known, and so automatically put on the
       
   544 	RPN stack.
       
   545 	
       
   546 	This means that an OR right node is automatically put on the
       
   547 	RPN stack at a known point, which is used to stress test failing
       
   548 	to append an OR right expression in OOM.
       
   549 
       
   550 	@param	aRemainingLevels Number of levels to generate after this.
       
   551 							If aRemainingLevels == 1 this function
       
   552 							generates an OR node.  Otherwise it creates
       
   553 							and AND node as described above.
       
   554  */
       
   555 	{
       
   556 	return (aRemainingLevels == 1)
       
   557 		?	AuthOr(AuthExpr(KTestPluginId1), AuthExpr(KTestPluginId1))
       
   558 		:	AuthAnd(AuthExpr(KTestPluginId1), BuildSuccessfulOr(aRemainingLevels - 1));
       
   559 	}
       
   560 
       
   561 
       
   562 void CTStepAuthExprEval::TestRPNReallocL()
       
   563 /**
       
   564 	Create a deeply nested expression which is
       
   565 	deep enough that the evaluator has to reallocate
       
   566 	its RPN stack, and checks the evaluation fails
       
   567 	gracefully in OOM.
       
   568  */
       
   569 	{
       
   570 	__UHEAP_MARK;
       
   571 	
       
   572 	RunOomTestsL(BuildLeftAnd, KTestPluginId1, 0);
       
   573 	RunOomTestsL(BuildRightAnd, KTestPluginId1, 0);
       
   574 	RunOomTestsL(BuildBalancedAnd, KTestPluginId1, 0);
       
   575 	RunOomTestsL(BuildFailedAnd, KUnknownIdentity, 1);
       
   576 	RunOomTestsL(BuildSuccessfulOr, KTestPluginId1, 1);
       
   577 	
       
   578 	__UHEAP_MARKEND;
       
   579 	}
       
   580 
       
   581 	
       
   582 void CTStepAuthExprEval::RunOomTestsL(
       
   583 	TAuthExpressionWrapper (*aAllocator)(TInt),
       
   584 	TIdentityId aExpectedIdentity, TInt aInitDepth)
       
   585 /**
       
   586 	Attempt to evaluate the supplied expresision in OOM.
       
   587 	
       
   588 	Running in OOM will both fail the evaluation, when the
       
   589 	plugin interface attempts to append to the call log, and
       
   590 	when the evaluator attempts to extend the RPN stack.
       
   591 	
       
   592 	OOM can only be tested in debug builds.  In release builds,
       
   593 	this function evaluates the expression at each depth and
       
   594 	tests the evaluator produces the correct result.
       
   595 	
       
   596 	@param	aAllocator		Function which allocates the expression.
       
   597 	@param	aExpectedIdentity Identity which should be returned on
       
   598 							successful evaluation.
       
   599 	@param	aInitDepth		Initial depth.
       
   600  */
       
   601 	{
       
   602 	CLaunchEval* le = CLaunchEval::NewL();
       
   603 	User::LeaveIfNull(le);
       
   604 	CleanupStack::PushL(le);
       
   605 	
       
   606 	const volatile TTestClientInterface& cli = le->iClientInterface;
       
   607 	
       
   608 	// depth starts at zero because, even though RPN stack
       
   609 	// is not used, the evaluator will attempt to grow its
       
   610 	// call log, and so fail the evaluation.  (This test is
       
   611 	// therefore also used to test failed plugin evaluations.)
       
   612 	
       
   613 	// max depth is 13 because CStepControl::StartL creates
       
   614 	// a worker thread with a 1MB maximum heap.  The
       
   615 	// number of allocated node cells for a balanced tree
       
   616 	// is 2^(depth+1) - 1.  When depth==13, there are
       
   617 	// 16383 cells using 327,672 bytes excluding cell headers.
       
   618 	// Allocation fails for depth == 14.
       
   619 	
       
   620 	const TInt KMaxDepth = 13;
       
   621 	for (TInt depth = aInitDepth; depth <= KMaxDepth; ++depth)
       
   622 		{
       
   623 		CAuthExpression* ae = aAllocator(depth);
       
   624 		User::LeaveIfNull(ae);
       
   625 		CleanupStack::PushL(ae);
       
   626 		
       
   627 		// OOM testing only available in debug builds
       
   628 #ifndef _DEBUG
       
   629 		le->Evaluate(ae);
       
   630 		TESTL(cli.iMode == TTestClientInterface::ESucceeded);
       
   631 		TESTL(cli.iIdentityId == aExpectedIdentity);
       
   632 #else
       
   633 		TInt i = 0;
       
   634 		do
       
   635 			{
       
   636 			// Ideally, the heap would be marked before and
       
   637 			// after the evaluation.  However, CEvaluator uses
       
   638 			// an CArrayFixFlat<TIdentityId> to store the RPN stack.
       
   639 			// When the first item is inserted, it allocates a
       
   640 			// CBufBase object to hold the data.  This object
       
   641 			// is reset but not deleted when the RPN stack is
       
   642 			// reset, so there will be a heap imbalance of one
       
   643 			// if anything was added to the RPN stack, even though
       
   644 			// the stack is reset.
       
   645 			
       
   646 			TInt preSize;
       
   647 			TInt preCount = User::AllocSize(preSize);
       
   648 //			__UHEAP_MARK;
       
   649 			
       
   650 			__UHEAP_SETFAIL(RAllocator::EDeterministic, i);
       
   651 			le->Evaluate(ae);
       
   652 			__UHEAP_RESET;
       
   653 			
       
   654 			TESTL(	cli.iMode == TTestClientInterface::EFailed
       
   655 				||	cli.iMode == TTestClientInterface::ESucceeded);
       
   656 			
       
   657 			if (cli.iMode == TTestClientInterface::EFailed)
       
   658 				{
       
   659 				TESTL(cli.iReason == KErrNoMemory);
       
   660 				}
       
   661 			else
       
   662 				{
       
   663 				TESTL(cli.iIdentityId == aExpectedIdentity);
       
   664 				}
       
   665 			
       
   666 			// clear call log so heap checking will work
       
   667 			le->iPluginInterface.iCallLog.Reset();
       
   668 			++i;
       
   669 
       
   670 			TInt postSize;
       
   671 			TInt postCount = User::AllocSize(postSize);			
       
   672 			TESTL(postCount == preCount || postCount == preCount + 1);
       
   673 //			__UHEAP_MARKEND;
       
   674 			} while (cli.iMode != TTestClientInterface::ESucceeded);
       
   675 		
       
   676 		// test evaluation still succeeds and failed allocation
       
   677 		// was not ignored
       
   678 		TInt limit = 2 * i;
       
   679 		while (i++ < limit)
       
   680 			{
       
   681 			__UHEAP_SETFAIL(RAllocator::EDeterministic, i++);
       
   682 			le->Evaluate(ae);
       
   683 			__UHEAP_RESET;
       
   684 			
       
   685 			TESTL(cli.iMode == TTestClientInterface::ESucceeded);
       
   686 			TESTL(cli.iIdentityId == aExpectedIdentity);
       
   687 			}
       
   688 
       
   689 		// clear plugin call log to reset mem usage for next iteration.
       
   690 		le->iPluginInterface.iCallLog.Reset();
       
   691 #endif	// #else #ifndef _DEBUG
       
   692 		CleanupStack::PopAndDestroy(ae);
       
   693 		}
       
   694 	
       
   695 	CleanupStack::PopAndDestroy(le);
       
   696 	}
       
   697