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 |
|