1 /* |
|
2 * Copyright (c) 2007 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 "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: Class definition of CDiagPluginExecPlanImpl |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // CLASS DECLARATION |
|
20 #include "diagpluginexecplanimpl.h" |
|
21 |
|
22 // SYSTEM INCLUDE FILES |
|
23 #include <e32def.h> |
|
24 #include <cstack.h> // CStack |
|
25 #include <DiagPlugin.h> // MDiagPlugin |
|
26 #include <DiagSuitePlugin.h> // MDiagSuitePlugin |
|
27 #include <DiagTestPlugin.h> // MDiagTestPlugin |
|
28 #include <DiagPluginPool.h> // CDiagPluginPool |
|
29 #include <DiagResultsDatabase.h> // RDiagResultsDatabaseRecord |
|
30 #include <DiagResultsDbItemBuilder.h> // CDiagResultsDbItemBuilder |
|
31 #include <DiagResultDetail.h> // MDiagResultDetail |
|
32 #include <DiagFrameworkDebug.h> // For debug log |
|
33 #include <DiagResultsDbRecordEngineParam.h> // CDiagResultsDbRecordEngineParam |
|
34 |
|
35 // USER INCLUDE FILES |
|
36 #include "diagframework.pan" // panic codes |
|
37 #include "diagexecplanentryimpl.h" // CDiagExecPlanEntryImpl |
|
38 #include "diagexecplanentryimpltest.h" // CDiagExecPlanEntryImplTest |
|
39 #include "diagexecplanentryimplsuite.h" // CDiagExecPlanEntryImplSuite |
|
40 #include "diagcleanupresetanddestroy.h" // CleanupRPointerArrayPushL |
|
41 #include "diagengineconfig.h" // TDiagEngineConfig |
|
42 |
|
43 |
|
44 // DATA |
|
45 |
|
46 // MACROS |
|
47 // Uncomment the line below to enable more plan creation log. |
|
48 // #define _DEBUG_EXEC_PLAN |
|
49 |
|
50 |
|
51 // LOCAL DATA TYPES |
|
52 /** |
|
53 * Used for keeping track of suite level stack. |
|
54 * It is used in InsertSuiteTransitionsL() function. ( STEP_5 ) |
|
55 */ |
|
56 struct TTransitionStackEntry |
|
57 { |
|
58 /** |
|
59 * iLeavelUid - Uid of the current level. |
|
60 */ |
|
61 TUid iLevelUid; |
|
62 |
|
63 /** |
|
64 * iPrepareIndex - Index in the plan where ETypeSuitePrepare entry is. |
|
65 * This information is used to update the suite iAsDependent field. |
|
66 */ |
|
67 TInt iPrepareIndex; |
|
68 }; |
|
69 |
|
70 |
|
71 // ======== LOCAL FUNCTIONS ======== |
|
72 |
|
73 |
|
74 // ======== MEMBER FUNCTIONS ======== |
|
75 |
|
76 // --------------------------------------------------------------------------- |
|
77 // CDiagPluginExecPlanImpl::NewL |
|
78 // --------------------------------------------------------------------------- |
|
79 // |
|
80 CDiagPluginExecPlanImpl* CDiagPluginExecPlanImpl::NewL( |
|
81 MDiagEngineCommon& aEngine, |
|
82 const TDiagEngineConfig& aEngineConfig, |
|
83 MDiagExecPlanEntryImplObserver& aEntryObserver ) |
|
84 { |
|
85 CDiagPluginExecPlanImpl* self = new ( ELeave ) CDiagPluginExecPlanImpl( |
|
86 aEngine, |
|
87 aEngineConfig, |
|
88 aEntryObserver ); |
|
89 |
|
90 return self; |
|
91 } |
|
92 |
|
93 // --------------------------------------------------------------------------- |
|
94 // CDiagPluginExecPlanImpl::CDiagPluginExecPlanImpl |
|
95 // --------------------------------------------------------------------------- |
|
96 // |
|
97 CDiagPluginExecPlanImpl::CDiagPluginExecPlanImpl( |
|
98 MDiagEngineCommon& aEngine, |
|
99 const TDiagEngineConfig& aEngineConfig, |
|
100 MDiagExecPlanEntryImplObserver& aEntryObserver ) |
|
101 : CActive( EPriorityLow ), |
|
102 iEngine( aEngine ), |
|
103 iEngineConfig( aEngineConfig ), |
|
104 iPlanEntryObserver( aEntryObserver ) |
|
105 { |
|
106 CActiveScheduler::Add( this ); |
|
107 } |
|
108 |
|
109 // --------------------------------------------------------------------------- |
|
110 // CDiagPluginExecPlanImpl::~CDiagPluginExecPlanImpl |
|
111 // --------------------------------------------------------------------------- |
|
112 // |
|
113 CDiagPluginExecPlanImpl::~CDiagPluginExecPlanImpl() |
|
114 { |
|
115 Cancel(); |
|
116 iPlan.ResetAndDestroy(); |
|
117 iPlan.Close(); |
|
118 iExecutedEntries.ResetAndDestroy(); |
|
119 iExecutedEntries.Close(); |
|
120 } |
|
121 |
|
122 |
|
123 // --------------------------------------------------------------------------- |
|
124 // CDiagPluginExecPlanImpl::InitaliazeL |
|
125 // Creating a fresh session. |
|
126 // --------------------------------------------------------------------------- |
|
127 // |
|
128 void CDiagPluginExecPlanImpl::InitializeL( TRequestStatus& aStatus, |
|
129 const RPointerArray< MDiagPlugin >& aBatch ) |
|
130 { |
|
131 LOGSTRING( "CDiagPluginExecPlanImpl::InitializeL: new session") |
|
132 |
|
133 __ASSERT_ALWAYS( iState == EStateIdle, Panic( EDiagFrameworkInternal ) ); |
|
134 |
|
135 aStatus = KRequestPending; |
|
136 iClientStatus = &aStatus; |
|
137 |
|
138 iExecutedEntries.ResetAndDestroy(); |
|
139 iPlan.ResetAndDestroy(); |
|
140 iResumeIndex = 0; |
|
141 |
|
142 // pre-step execution step. copy the argument to a local plan |
|
143 TInt i; |
|
144 for ( i = 0; i < aBatch.Count(); i++ ) |
|
145 { |
|
146 __ASSERT_ALWAYS( aBatch[i] != NULL, Panic( EDiagFrameworkBadArgument ) ); |
|
147 |
|
148 CDiagExecPlanEntryImpl* newEntry = CreateDefaultPlanEntryLC( |
|
149 *(aBatch[i]), |
|
150 EFalse ); // aAsDependency |
|
151 |
|
152 iPlan.AppendL( newEntry ); // ownership transferred. |
|
153 CleanupStack::Pop( newEntry ); |
|
154 newEntry = NULL; |
|
155 } |
|
156 |
|
157 LOGSTRING( "CDiagPluginExecPlanImpl::InitializeL: Initial Batch" ) |
|
158 LogPlanL(); |
|
159 |
|
160 ChangeState( EStateExpandDependencyAndSuites ); |
|
161 } |
|
162 |
|
163 // --------------------------------------------------------------------------- |
|
164 // CDiagPluginExecPlanImpl::InitializeL |
|
165 // Continuing from incomplete session. |
|
166 // --------------------------------------------------------------------------- |
|
167 // |
|
168 void CDiagPluginExecPlanImpl::InitializeL( TRequestStatus& aStatus ) |
|
169 { |
|
170 LOGSTRING( "CDiagPluginExecPlanImpl::InitaliazeL: continue" ) |
|
171 |
|
172 // validate input. |
|
173 __ASSERT_ALWAYS( iState == EStateIdle, Panic( EDiagFrameworkInternal ) ); |
|
174 |
|
175 // if we are resuming incomplete session, it must incomplete. |
|
176 TBool isRecordCompleted = EFalse; |
|
177 User::LeaveIfError( iEngine.DbRecord().IsTestCompleted( isRecordCompleted ) ); |
|
178 __ASSERT_ALWAYS( !isRecordCompleted, Panic( EDiagFrameworkBadArgument ) ); |
|
179 |
|
180 aStatus = KRequestPending; |
|
181 iClientStatus = &aStatus; |
|
182 iResumeIndex = 0; |
|
183 |
|
184 iExecutedEntries.ResetAndDestroy(); |
|
185 iPlan.ResetAndDestroy(); |
|
186 |
|
187 // Retrieve records from database and use it as base for creating |
|
188 // a new plan. |
|
189 RPointerArray< CDiagResultsDatabaseItem > previousResults; |
|
190 DiagFwInternal::CleanupRPointerArrayPushL< CDiagResultsDatabaseItem >( &previousResults ); |
|
191 |
|
192 User::LeaveIfError( |
|
193 iEngine.DbRecord().GetTestResults( previousResults ) ); |
|
194 |
|
195 TInt resultCount = previousResults.Count(); |
|
196 for( TInt i = 0; i < resultCount; i++ ) |
|
197 { |
|
198 // Get the test plug-in. |
|
199 // Note that FindPlugin does not transfer ownership and hence testPlugin |
|
200 // and does not need to be deallocated. |
|
201 MDiagPlugin& testPlugin = |
|
202 iEngine.PluginPool().FindPluginL( previousResults[i]->TestUid() ); |
|
203 |
|
204 // This should have been a test plug-in |
|
205 __ASSERT_DEBUG( testPlugin.Type() == MDiagPlugin::ETypeTestPlugin, |
|
206 Panic( EDiagFrameworkInternal ) ); |
|
207 |
|
208 CDiagExecPlanEntryImplTest* testEntry = |
|
209 CDiagExecPlanEntryImplTest::NewLC( |
|
210 iEngine, |
|
211 iEngineConfig, |
|
212 iPlanEntryObserver, |
|
213 static_cast< MDiagTestPlugin& >( testPlugin ), |
|
214 previousResults[i]->WasDependency(), |
|
215 previousResults[i]->TestResult() ); |
|
216 |
|
217 if ( testEntry->Result() == CDiagResultsDatabaseItem::EQueuedToRun ) |
|
218 { |
|
219 // it was queued to be executed. |
|
220 iPlan.AppendL( testEntry ); // ownership transferred. |
|
221 } |
|
222 else |
|
223 { |
|
224 // it was already executed. |
|
225 iExecutedEntries.AppendL( testEntry ); // ownership transferred. |
|
226 } |
|
227 CleanupStack::Pop( testEntry ); |
|
228 testEntry = NULL; |
|
229 } |
|
230 |
|
231 CleanupStack::PopAndDestroy( &previousResults ); |
|
232 |
|
233 iResumeIndex = iExecutedEntries.Count(); |
|
234 |
|
235 if ( iResumeIndex != 0 ) |
|
236 { |
|
237 LOGSTRING( "CDiagPluginExecPlanImpl::InitializeL: Queued Items" ) |
|
238 LogPlanL(); |
|
239 |
|
240 ChangeState( EStateExpandDependencyAndSuites ); |
|
241 } |
|
242 else |
|
243 { |
|
244 LOGSTRING( "CDiagPluginExecPlanImpl::InitializeL: " |
|
245 L"Items in DB may be invalid. Fully recreate plan" ) |
|
246 |
|
247 // If iResumeIndex is 0, it means that all items in the db are |
|
248 // marked as EQueuedToRun. Because of the async nature of db, |
|
249 // it could also indicate that not previous plan was not fully |
|
250 // written to the database. In this case, read the engine parameter |
|
251 // and try to recreate the plan from scratch. |
|
252 // |
|
253 // If it was already fully written but hadn't had a chance to really |
|
254 // execute anything, this will not cause any ill effects since |
|
255 // plan created should be identical and simply reset |
|
256 // all results in db to EQueuedToRun. |
|
257 iExecutedEntries.ResetAndDestroy(); |
|
258 iPlan.ResetAndDestroy(); |
|
259 |
|
260 RPointerArray< MDiagPlugin > batch; |
|
261 CleanupClosePushL( batch ); // items are not owned, so no need for "Destroy" |
|
262 |
|
263 CDiagResultsDbRecordEngineParam* engineParam = NULL; |
|
264 User::LeaveIfError( |
|
265 iEngine.DbRecord().GetEngineParam( engineParam ) ); |
|
266 |
|
267 CleanupStack::PushL( engineParam ); |
|
268 |
|
269 const RArray< TUid >& batchUids = engineParam->ExecutionsUidArray(); |
|
270 |
|
271 // Read original Uids from previous engine param. |
|
272 for( TInt i = 0; i < batchUids.Count(); i++ ) |
|
273 { |
|
274 MDiagPlugin* testPlugin = NULL; |
|
275 User::LeaveIfError( |
|
276 iEngine.PluginPool().FindPlugin( batchUids[i], testPlugin ) ); |
|
277 |
|
278 __ASSERT_DEBUG( testPlugin != NULL, Panic( EDiagFrameworkInternal ) ); |
|
279 if ( testPlugin ) //lint !e774 This will be evaluated on non-debug build. |
|
280 { |
|
281 batch.AppendL( testPlugin ); |
|
282 } |
|
283 } |
|
284 |
|
285 CleanupStack::PopAndDestroy( engineParam ); |
|
286 engineParam = NULL; |
|
287 |
|
288 // Call the normal InitializeL() method as if it is a new session. |
|
289 InitializeL( aStatus, batch ); |
|
290 |
|
291 CleanupStack::PopAndDestroy( &batch ); // calls Close() |
|
292 } |
|
293 } |
|
294 |
|
295 // --------------------------------------------------------------------------- |
|
296 // CDiagPluginExecPlanImpl::operator[] |
|
297 // --------------------------------------------------------------------------- |
|
298 // |
|
299 CDiagExecPlanEntryImpl& CDiagPluginExecPlanImpl::operator[]( TInt aIndex ) |
|
300 { |
|
301 return *iPlan[aIndex]; |
|
302 } |
|
303 |
|
304 // --------------------------------------------------------------------------- |
|
305 // CDiagPluginExecPlanImpl::CurrentExecutionItem |
|
306 // --------------------------------------------------------------------------- |
|
307 // |
|
308 CDiagExecPlanEntryImpl& CDiagPluginExecPlanImpl::CurrentExecutionItem() |
|
309 { |
|
310 return *iPlan[iExecutionCursor]; |
|
311 } |
|
312 |
|
313 // --------------------------------------------------------------------------- |
|
314 // CDiagPluginExecPlanImpl::ResetExecutionCursor |
|
315 // --------------------------------------------------------------------------- |
|
316 // |
|
317 void CDiagPluginExecPlanImpl::ResetExecutionCursor() |
|
318 { |
|
319 iExecutionCursor = 0; |
|
320 } |
|
321 |
|
322 // --------------------------------------------------------------------------- |
|
323 // CDiagPluginExecPlanImpl::MoveCursorToNext |
|
324 // --------------------------------------------------------------------------- |
|
325 // |
|
326 TBool CDiagPluginExecPlanImpl::MoveCursorToNext() |
|
327 { |
|
328 TBool value = EFalse; |
|
329 |
|
330 if ( iExecutionCursor < iPlan.Count() - 1 ) |
|
331 { |
|
332 iExecutionCursor++; |
|
333 value = ETrue; |
|
334 } |
|
335 else |
|
336 { |
|
337 // cannot move beyond the last item. |
|
338 } |
|
339 |
|
340 return value; |
|
341 } |
|
342 |
|
343 // ======== From CActive ========= |
|
344 // --------------------------------------------------------------------------- |
|
345 // From CActive |
|
346 // CDiagPluginExecPlanImpl::RunL |
|
347 // --------------------------------------------------------------------------- |
|
348 // |
|
349 void CDiagPluginExecPlanImpl::RunL() |
|
350 { |
|
351 /*---------------------------------------------------------------------- |
|
352 Create execution plan: |
|
353 Overview: |
|
354 |
|
355 STEP_1. Expand Dependency |
|
356 STEP_2. Expand Suites. |
|
357 STEP_3. Repeat STEP_1 & STEP_2 until no changes are made to the plan |
|
358 STEP_4. Check and remove empty suites |
|
359 STEP_5. Add Prepare/Finalize suite execution. |
|
360 STEP_6. Store execution plan to results db. |
|
361 STEP_7. Append items that were executed in the previous test |
|
362 to the beginning of the test. |
|
363 |
|
364 Details: |
|
365 STEP_1. Expand Dependency |
|
366 In this step, each item is checked for dependency and |
|
367 dependent items will be inserted into plan. |
|
368 Note that if dependent item also depends on something else, those |
|
369 will be added immediately. |
|
370 |
|
371 All items inserted during this phase is inserted as dependent. |
|
372 |
|
373 STEP_2. Expand suites |
|
374 Suites are expandeded to individual tests or suites. Suite |
|
375 item will be expanded between parent suite's Prepare and |
|
376 Finalize items. |
|
377 |
|
378 iAsDependent value will be inherited from the parent suite |
|
379 that it expanded from. E.g. if suite was dependent, then so will |
|
380 all the items that included from that suite. |
|
381 |
|
382 Note that it does not remove the original suite entry in the plan. |
|
383 This is to make sure that dependencies inserted will be grouped |
|
384 within the same group as the plug-ins that depended on it. |
|
385 If they are removed, and re-inserted later in STEP_5, it will |
|
386 cause the dependent items to be outside of the original grouping. |
|
387 e.g. S1 = {P1} |
|
388 S2 = {P2, P3} |
|
389 |
|
390 and P2 depends on P1 |
|
391 |
|
392 When dependency and suites are expanded with original |
|
393 suite removed, after STEP_3, the plan will look like this: |
|
394 (* indicates iAsDependent == ETrue) |
|
395 |
|
396 0 1 2 |
|
397 *P1 P2 P3 |
|
398 |
|
399 When it tries to add suite transition back in to the plan, |
|
400 it will look like this: |
|
401 (* indicates iAsDependent == ETrue) |
|
402 (< indicates suite prepare execution.) |
|
403 (> indicates suite finalize execution.) |
|
404 |
|
405 0 1 2 3 4 5 6 |
|
406 <S1 *P1 S1> <S2 P2 P3 S2> |
|
407 |
|
408 which is somewhat incorrect since *P1 is added due to |
|
409 dependency. |
|
410 |
|
411 Instead, if original suite grouping is kept, after STEP_3 |
|
412 |
|
413 0 1 2 3 4 |
|
414 <S2 *P1 P2 P3 S2> |
|
415 |
|
416 After STEP_5 |
|
417 |
|
418 0 1 2 3 4 5 6 |
|
419 <S2 <S1 *P1 S1> P2 P3 S2> |
|
420 |
|
421 which is more correct. |
|
422 |
|
423 Note that this will be done in breadth first style. If there is a |
|
424 nested suites, it will not be expanded until next cycle. |
|
425 This is to allow dependencies of the suite to be expanded before |
|
426 being removed. |
|
427 |
|
428 STEP_3. Repeat STEP_1 & STEP_2 until no changes are made. |
|
429 This step ensures that suites are expanded, and all dependent |
|
430 items are added to the plan. |
|
431 |
|
432 STEP_4. Remove Empty suites |
|
433 Because dependent items can be moved, it is possible that plan ends |
|
434 up with empty suites. This section will check for |
|
435 suite prepare/finalize that has nothing inside, and remove them. |
|
436 |
|
437 STEP_5. Add Prepare/Finalize steps for suites. |
|
438 As a final step, it will navigate all the entries in the plan, and |
|
439 insert proper prepare/finalize steps. This is based on stack, |
|
440 where every suite prepare is pushed into a stack, and poped when |
|
441 suite finalize is called. e.g. consider following plug-ins: |
|
442 |
|
443 S1 = { P1, P2 } |
|
444 S2 = { P3, P4 } |
|
445 |
|
446 And P3 depends on P2. |
|
447 |
|
448 And resulting plan after STEP_4 looked like this: |
|
449 |
|
450 0 1 2 3 4 |
|
451 <S2 *P2 P3 P4 S2> |
|
452 |
|
453 After STEP_5, it should look like this: |
|
454 |
|
455 0 1 2 3 4 5 6 |
|
456 <S2 <S1 *P2 S1> P3 P4 S2> |
|
457 |
|
458 STEP_6. Store execution plan to results db. |
|
459 This allows continuation of the incomplete results. |
|
460 Only test plug-ins are written to the database. |
|
461 |
|
462 STEP_7. Append items that were executed in the previous test |
|
463 to the beginning of the test. |
|
464 |
|
465 Other Notes: |
|
466 |
|
467 NOTE_1) This logic currently does not check for circular dependencies. |
|
468 If circular dependency exists, the program will go into an |
|
469 infinite loop in ExpandDependenciesL(). |
|
470 |
|
471 NOTE_2) Inserting duplicate items. |
|
472 Due to dependencies, duplicate entries may exist in the plan. |
|
473 |
|
474 When items are inserted during STEP_1 - STEP_2, it will be checked |
|
475 for duplicates. |
|
476 |
|
477 Duplicate removal policy is as follows: |
|
478 RULE_A) If an item with "iAsDependent == ETrue" is being inserted, |
|
479 AND if an item already exist in the plan before current index, |
|
480 then it will not be inserted. |
|
481 |
|
482 RULE_B) Any items inserted with "iAsDependent == EFalse" will |
|
483 always be inserted at the requested index. |
|
484 This is because they are considered to be user input, and |
|
485 plan will not try to re-order the execution order that |
|
486 client or user has specified. |
|
487 |
|
488 RULE_C) The first instance of an item has higher priority than later |
|
489 instances. Later instace of duplicate will be removed, unless |
|
490 it violates RULE_B. (e.g. item has "iAsDependent == EFalse".) |
|
491 |
|
492 This has a side effect: item may execute twice in certain cases. |
|
493 E.g. original plan has two plug-ins: P1, P2, P3 |
|
494 P1 depends on P2, and P3 also depends ond P2 |
|
495 |
|
496 Original Input: 0 1 2 |
|
497 P1 P2 P3 |
|
498 |
|
499 After STEP_3, it should look like this. |
|
500 (* indicates iAsDependent == ETrue) |
|
501 |
|
502 0 1 2 3 4 |
|
503 *P2 P1 P2 *P2 P3 |
|
504 |
|
505 During STEP_4, duplicates are removed, and it should look like this: |
|
506 (* indicates iAsDependent == ETrue) |
|
507 |
|
508 0 1 2 4 |
|
509 *P2 P1 P2 P3 |
|
510 |
|
511 Note that there are two P2s in the plan; |
|
512 at 0 with iAsDependent == ETrue and at 2 with iAsDependent == EFalse |
|
513 |
|
514 There may be some discussions on whether this is how it should be. |
|
515 However, at this point, it seems that it is more important that |
|
516 execution appears to the user in the order specified. |
|
517 |
|
518 To make sure that user sees that P2 is executed only once, plug-in |
|
519 developer may need to make sure that if a plug-in provides services, |
|
520 it should also handle cases where it is executed twice. |
|
521 |
|
522 In reality, such cases can be avoided by grouping the plug-ins |
|
523 in the correct order, hence it should not be an issue. |
|
524 |
|
525 ----------------------------------------------------------------------*/ |
|
526 |
|
527 // First, error handling. |
|
528 LOGSTRING3( "CDiagPluginExecPlanImpl::RunL: State = %d, Err = %d", |
|
529 iState, iStatus.Int() ) |
|
530 |
|
531 User::LeaveIfError( iStatus.Int() ); |
|
532 |
|
533 switch ( iState ) |
|
534 { |
|
535 case EStateExpandDependencyAndSuites: |
|
536 { |
|
537 LOGSTRING( "CDiagPluginExecPlanImpl::RunL: STEP_1") |
|
538 // STEP_1. Expand dependency. |
|
539 if ( !iEngineConfig.IsDependencyDisabled() ) |
|
540 { |
|
541 ExpandDependenciesL(); |
|
542 } |
|
543 |
|
544 LOGSTRING( "CDiagPluginExecPlanImpl::RunL: STEP_2") |
|
545 // STEP_2. Expand suites. |
|
546 if ( ExpandSuitesL() ) |
|
547 { |
|
548 // STEP_3. Repeat STEP_1, STEP_2 until no changes are made. |
|
549 // Do a self transition to repeat STEP_1 and STEP_2 |
|
550 ChangeState( EStateExpandDependencyAndSuites ); |
|
551 } |
|
552 else |
|
553 { |
|
554 // no changes are made to the plan. Move to STEP_4 |
|
555 ChangeState( EStateRemoveEmptySuites ); |
|
556 } |
|
557 } |
|
558 break; |
|
559 |
|
560 case EStateRemoveEmptySuites: |
|
561 LOGSTRING( "CDiagPluginExecPlanImpl::RunL: STEP_4") |
|
562 // STEP_4. Remove empty suites. This can happen because of duplicate |
|
563 // dependencies moving later dependent test to earlier position. |
|
564 RemoveEmptySuites(); |
|
565 |
|
566 #ifdef _DEBUG_EXEC_PLAN |
|
567 LOGSTRING( "CDiagPluginExecPlanImpl:CreatePlanL: " |
|
568 L"Before Inserting Suite Transtions" ) |
|
569 LogPlanL(); |
|
570 #endif // _DEBUG_EXEC_PLAN |
|
571 |
|
572 // Continue to STEP_5 |
|
573 ChangeState( EStateInsertSuiteTransitions ); |
|
574 break; |
|
575 |
|
576 case EStateInsertSuiteTransitions: |
|
577 LOGSTRING( "CDiagPluginExecPlanImpl::RunL: STEP_5 - Insert Suite Transtions") |
|
578 // STEP_5. Add pre/post suite execution |
|
579 InsertSuiteTransitionsL(); |
|
580 |
|
581 // STEP_6. Store plan to db. |
|
582 LOGSTRING( "CDiagPluginExecPlanImpl::RunL: STEP_6 - Store to db") |
|
583 // this time, manually update state, since storing |
|
584 // to database needs to use iStatus |
|
585 iState = EStateStoreToDb; |
|
586 |
|
587 // Move cursor to one before so that it can start checking from |
|
588 // the beginning. StoreNextTestPluginToDbL() will move the cursor |
|
589 // as soon as it enters. |
|
590 iExecutionCursor = -1; |
|
591 StoreNextTestPluginToDbL(); |
|
592 |
|
593 break; |
|
594 |
|
595 case EStateStoreToDb: |
|
596 LOGSTRING2( "CDiagPluginExecPlanImpl::RunL: STEP_6 - " |
|
597 L"item 0x%08x stored.", |
|
598 iPlan[iExecutionCursor]->Plugin().Uid().iUid ) |
|
599 |
|
600 StoreNextTestPluginToDbL(); |
|
601 break; |
|
602 |
|
603 case EStatePlanCreated: |
|
604 // STEP_7. Prepend the items that were executed in last session |
|
605 // to the beginning of the execution plan. |
|
606 LOGSTRING( "CDiagPluginExecPlanImpl::RunL: STEP_7 - prepend executed items" ) |
|
607 PrependExecutedItemsL(); |
|
608 |
|
609 LOGSTRING( "CDiagPluginExecPlanImpl::RunL: Final Plan" ) |
|
610 LogPlanL(); |
|
611 |
|
612 LOGSTRING2( "CDiagPluginExecPlanImpl::RunL: Resume at index %d", iResumeIndex ) |
|
613 |
|
614 LogPlanInRecordL(); |
|
615 |
|
616 ResetExecutionCursor(); |
|
617 |
|
618 ReportResult( KErrNone ); |
|
619 break; |
|
620 |
|
621 case EStateIdle: |
|
622 default: |
|
623 __ASSERT_DEBUG( 0, Panic( EDiagFrameworkInternal ) ); |
|
624 break; |
|
625 } |
|
626 } |
|
627 |
|
628 // --------------------------------------------------------------------------- |
|
629 // From CActive |
|
630 // CDiagPluginExecPlanImpl::DoCancel |
|
631 // --------------------------------------------------------------------------- |
|
632 // |
|
633 void CDiagPluginExecPlanImpl::DoCancel() |
|
634 { |
|
635 iPlan.ResetAndDestroy(); |
|
636 iExecutedEntries.ResetAndDestroy(); |
|
637 iState = EStateIdle; |
|
638 |
|
639 ReportResult( KErrCancel ); |
|
640 } |
|
641 |
|
642 // --------------------------------------------------------------------------- |
|
643 // From CActive |
|
644 // CDiagPluginExecPlanImpl::RunError |
|
645 // --------------------------------------------------------------------------- |
|
646 // |
|
647 TInt CDiagPluginExecPlanImpl::RunError( TInt aError ) |
|
648 { |
|
649 iPlan.ResetAndDestroy(); |
|
650 iExecutedEntries.ResetAndDestroy(); |
|
651 iState = EStateIdle; |
|
652 |
|
653 ReportResult( aError ); |
|
654 |
|
655 return KErrNone; |
|
656 } |
|
657 |
|
658 // --------------------------------------------------------------------------- |
|
659 // From MDiagPluginExecPlan |
|
660 // CDiagPluginExecPlanImpl::CurrentIndex |
|
661 // --------------------------------------------------------------------------- |
|
662 // |
|
663 TInt CDiagPluginExecPlanImpl::CurrentIndex() const |
|
664 { |
|
665 return iExecutionCursor; |
|
666 } |
|
667 |
|
668 |
|
669 // --------------------------------------------------------------------------- |
|
670 // From MDiagPluginExecPlan |
|
671 // CDiagPluginExecPlanImpl::CurrentTestIndex |
|
672 // --------------------------------------------------------------------------- |
|
673 // |
|
674 TInt CDiagPluginExecPlanImpl::CurrentTestIndex( TBool aIncludeDependency ) const |
|
675 { |
|
676 TInt count = 0; |
|
677 |
|
678 for ( TInt i = 0; i < iPlan.Count() && i < iExecutionCursor; i++ ) |
|
679 { |
|
680 if ( iPlan[i]->Plugin().Type() == MDiagPlugin::ETypeTestPlugin ) |
|
681 { |
|
682 // if caller wants to include both explicit and dependent |
|
683 // or if plug-in is not depentent test, count. |
|
684 if ( aIncludeDependency || ( !iPlan[i]->AsDependency() ) ) |
|
685 { |
|
686 count++; |
|
687 } |
|
688 } |
|
689 } |
|
690 |
|
691 // subtract 1 if we only went past the last test. |
|
692 if ( count >= TestCount( aIncludeDependency ) ) |
|
693 { |
|
694 count--; |
|
695 } |
|
696 return count; |
|
697 } |
|
698 |
|
699 |
|
700 // --------------------------------------------------------------------------- |
|
701 // From MDiagPluginExecPlan |
|
702 // CDiagPluginExecPlanImpl::TestCount |
|
703 // --------------------------------------------------------------------------- |
|
704 // |
|
705 TInt CDiagPluginExecPlanImpl::TestCount( TBool aIncludeDependency ) const |
|
706 { |
|
707 TInt count = 0; |
|
708 |
|
709 for ( TInt i = 0; i < iPlan.Count(); i++ ) |
|
710 { |
|
711 if ( iPlan[i]->Plugin().Type() == MDiagPlugin::ETypeTestPlugin ) |
|
712 { |
|
713 // if caller wants to include both explicit and dependent |
|
714 // or if plug-in is not depentent test, count. |
|
715 if ( aIncludeDependency || ( !iPlan[i]->AsDependency() ) ) |
|
716 count++; |
|
717 } |
|
718 } |
|
719 return count; |
|
720 } |
|
721 |
|
722 // --------------------------------------------------------------------------- |
|
723 // From MDiagPluginExecPlan |
|
724 // CDiagPluginExecPlanImpl::operator[] () const |
|
725 // --------------------------------------------------------------------------- |
|
726 // |
|
727 const MDiagExecPlanEntry& CDiagPluginExecPlanImpl::operator[] ( TInt aIndex ) const |
|
728 { |
|
729 __ASSERT_ALWAYS( aIndex >= 0 && aIndex < iPlan.Count(), |
|
730 Panic( EDiagFrameworkArrayBounds ) ); |
|
731 return *( static_cast< MDiagExecPlanEntry* >( iPlan[aIndex] ) ); |
|
732 } |
|
733 |
|
734 // --------------------------------------------------------------------------- |
|
735 // From MDiagPluginExecPlan |
|
736 // CDiagPluginExecPlanImpl::CurrentExecutionItem const |
|
737 // --------------------------------------------------------------------------- |
|
738 // |
|
739 const MDiagExecPlanEntry& CDiagPluginExecPlanImpl::CurrentExecutionItem() const |
|
740 { |
|
741 __ASSERT_ALWAYS( iExecutionCursor >= 0 && iExecutionCursor < iPlan.Count(), |
|
742 Panic( EDiagFrameworkArrayBounds ) ); |
|
743 return *( static_cast< MDiagExecPlanEntry* >( iPlan[iExecutionCursor] ) ); |
|
744 } |
|
745 |
|
746 |
|
747 // --------------------------------------------------------------------------- |
|
748 // From MDiagPluginExecPlan |
|
749 // CDiagPluginExecPlanImpl::IsLastTest |
|
750 // --------------------------------------------------------------------------- |
|
751 // |
|
752 TBool CDiagPluginExecPlanImpl::IsLastTest() const |
|
753 { |
|
754 if ( TestCount( ETrue ) == 0 ) |
|
755 { |
|
756 // there was no test in the plan.. |
|
757 // In this case, it is always ETrue. |
|
758 return ETrue; |
|
759 } |
|
760 |
|
761 return ( CurrentTestIndex( ETrue ) == TestCount( ETrue ) - 1 ); |
|
762 } |
|
763 |
|
764 // --------------------------------------------------------------------------- |
|
765 // From MDiagPluginExecPlan |
|
766 // CDiagPluginExecPlanImpl::IsLastPlugin |
|
767 // --------------------------------------------------------------------------- |
|
768 // |
|
769 TBool CDiagPluginExecPlanImpl::IsLastPlugin() const |
|
770 { |
|
771 if ( iPlan.Count() == 0 ) |
|
772 { |
|
773 // if plan was empty, always consider it to be the last. |
|
774 return ETrue; |
|
775 } |
|
776 |
|
777 return iExecutionCursor == ( iPlan.Count() -1 ); |
|
778 } |
|
779 |
|
780 |
|
781 // --------------------------------------------------------------------------- |
|
782 // From MDiagPluginExecPlan |
|
783 // CDiagPluginExecPlanImpl::Count |
|
784 // --------------------------------------------------------------------------- |
|
785 // |
|
786 TInt CDiagPluginExecPlanImpl::Count() const |
|
787 { |
|
788 return iPlan.Count(); |
|
789 } |
|
790 |
|
791 // --------------------------------------------------------------------------- |
|
792 // From MDiagPluginExecPlan |
|
793 // CDiagPluginExecPlanImpl::ResumeIndex |
|
794 // --------------------------------------------------------------------------- |
|
795 // |
|
796 TInt CDiagPluginExecPlanImpl::ResumeIndex() const |
|
797 { |
|
798 return iResumeIndex; |
|
799 } |
|
800 |
|
801 // --------------------------------------------------------------------------- |
|
802 // CDiagPluginExecPlanImpl::ChangeState |
|
803 // --------------------------------------------------------------------------- |
|
804 // |
|
805 void CDiagPluginExecPlanImpl::ChangeState( TState aState ) |
|
806 { |
|
807 LOGSTRING3( "CDiagPluginExecPlanImpl::ChangeState: state change %d -> %d", |
|
808 iState, aState ) |
|
809 |
|
810 iState = aState; |
|
811 |
|
812 TRequestStatus* stat = &iStatus; |
|
813 User::RequestComplete( stat, KErrNone ); |
|
814 SetActive(); |
|
815 } |
|
816 |
|
817 // --------------------------------------------------------------------------- |
|
818 // CDiagPluginExecPlanImpl::ExpandDependenciesL |
|
819 // --------------------------------------------------------------------------- |
|
820 // |
|
821 TBool CDiagPluginExecPlanImpl::ExpandDependenciesL() |
|
822 { |
|
823 // STEP_1. Expand dependency. |
|
824 // Before modifying this function, please see STEP_1 comments in CreatePlanL() |
|
825 TInt planIdx = 0; |
|
826 TBool planChanged( EFalse ); |
|
827 while ( planIdx < iPlan.Count() ) |
|
828 { |
|
829 TBool itemAdded = EFalse; |
|
830 |
|
831 // we are only interested in type ETypeTestExec or ETypeSuiteUnexpanded. |
|
832 // If it is ETypeSuitePrepare or ETypeSuiteFinalize, that means |
|
833 // that it is a suite and it has been already been expanded to |
|
834 // prepare/finalize. Since dependencies are resolved before suites |
|
835 // are expanded, we are not interested in re-evaluating expanded tests. |
|
836 if ( iPlan[planIdx]->Type() == CDiagExecPlanEntryImpl::ETypeTestExec || |
|
837 iPlan[planIdx]->Type() == CDiagExecPlanEntryImpl::ETypeSuiteUnexpanded ) |
|
838 { |
|
839 // dependencies should be rare. So granuality 1 should be fine. |
|
840 CPtrCArray* depList = new( ELeave )CPtrCArray( 1 ); |
|
841 CleanupStack::PushL( depList ); |
|
842 iPlan[planIdx]->Plugin().GetLogicalDependenciesL( *depList ); |
|
843 |
|
844 // iterate through the dependiencies BACKWARDS to make sure |
|
845 // that dependencies are inserted in the same order |
|
846 // specified. If it is not added backwards, developers may |
|
847 // be surprised that dependencies are executed |
|
848 // in reverse order of what is specified in the XML. |
|
849 for ( TInt depIdx = depList->Count() - 1; depIdx >= 0; depIdx-- ) |
|
850 { |
|
851 // If dependency is specified, but the dependent plug-in is |
|
852 // not found in plug-in pool, this probably means |
|
853 // plug-in database is corrupted. |
|
854 MDiagPlugin& plugin = iEngine.PluginPool().FindPluginL( ( *depList )[ depIdx ] ); |
|
855 |
|
856 if ( InsertPluginL( plugin, |
|
857 ETrue, |
|
858 planIdx ) ) |
|
859 { |
|
860 itemAdded = ETrue; |
|
861 } |
|
862 } |
|
863 CleanupStack::PopAndDestroy( depList ); |
|
864 depList = NULL; |
|
865 } |
|
866 |
|
867 // Advance to next item in plan only if no new item is added. |
|
868 // This ensures that items just added are re-evaluated for |
|
869 // dependency, and expand if it is an unexpanded suite. |
|
870 if ( !itemAdded ) |
|
871 { |
|
872 planIdx++; |
|
873 } |
|
874 else |
|
875 { |
|
876 planChanged = ETrue; |
|
877 } |
|
878 } |
|
879 |
|
880 return planChanged; |
|
881 } |
|
882 |
|
883 |
|
884 // --------------------------------------------------------------------------- |
|
885 // CDiagPluginExecPlanImpl::ExpandSuitesL |
|
886 // --------------------------------------------------------------------------- |
|
887 // |
|
888 TBool CDiagPluginExecPlanImpl::ExpandSuitesL() |
|
889 { |
|
890 // STEP_2. Expand suites. |
|
891 // Before modifying this function, please see STEP_1 comments in CreatePlanL() |
|
892 TBool planChanged = EFalse; |
|
893 TInt i = 0; |
|
894 while ( i < iPlan.Count() ) |
|
895 { |
|
896 if ( iPlan[i]->Type() == CDiagExecPlanEntryImpl::ETypeSuiteUnexpanded ) |
|
897 { |
|
898 // If it is unexpanded, it must be a suite. |
|
899 __ASSERT_DEBUG( iPlan[i]->Plugin().Type() == MDiagPlugin::ETypeSuitePlugin, |
|
900 Panic( EDiagFrameworkInternal ) ); |
|
901 planChanged = ETrue; |
|
902 |
|
903 // Change type from ETestExec to ETypeSuitePrepare. This indicates |
|
904 // that the suite item in the plan has been examined and |
|
905 // expanded. |
|
906 iPlan[i]->SetType( CDiagExecPlanEntryImpl::ETypeSuitePrepare ); |
|
907 |
|
908 // dependency is inherited |
|
909 TBool asDependency = iPlan[i]->AsDependency(); |
|
910 |
|
911 // Get Children from the plug-in |
|
912 MDiagSuitePlugin& suite = static_cast<MDiagSuitePlugin&>( iPlan[i]->Plugin() ); |
|
913 RPointerArray<MDiagPlugin> children; |
|
914 CleanupClosePushL( children ); |
|
915 |
|
916 suite.GetChildrenL( children, MDiagSuitePlugin::ESortByPosition ); |
|
917 |
|
918 i++; // insert rest after current item. |
|
919 |
|
920 TInt childIdx = 0; |
|
921 while ( childIdx < children.Count() ) |
|
922 { |
|
923 if ( InsertPluginL( *( children[childIdx] ), |
|
924 asDependency, |
|
925 i ) ) |
|
926 { |
|
927 // new item is added. Move to next |
|
928 i++; |
|
929 } |
|
930 childIdx++; |
|
931 } |
|
932 |
|
933 children.Reset(); // children pointers are not owned |
|
934 CleanupStack::PopAndDestroy( &children ); |
|
935 |
|
936 // insert suite finalize entry into plan |
|
937 CDiagExecPlanEntryImplSuite* finalizeEntry = |
|
938 CDiagExecPlanEntryImplSuite::NewLC( |
|
939 iEngine, |
|
940 iEngineConfig, |
|
941 iPlanEntryObserver, |
|
942 suite, |
|
943 asDependency, |
|
944 CDiagExecPlanEntryImpl::ETypeSuiteFinalize ); |
|
945 |
|
946 iPlan.InsertL( static_cast< CDiagExecPlanEntryImpl* >( finalizeEntry ), i ); |
|
947 CleanupStack::Pop( finalizeEntry ); // owership transferred |
|
948 finalizeEntry = NULL; |
|
949 i++; |
|
950 } |
|
951 else |
|
952 { |
|
953 // this one is not suite, so examine the next one. |
|
954 i++; |
|
955 } |
|
956 } |
|
957 |
|
958 return planChanged; |
|
959 } |
|
960 |
|
961 // Looking for STEP_3? It is in RunL() .. |
|
962 |
|
963 // --------------------------------------------------------------------------- |
|
964 // CDiagPluginExecPlanImpl::RemoveEmptySuites |
|
965 // --------------------------------------------------------------------------- |
|
966 // |
|
967 void CDiagPluginExecPlanImpl::RemoveEmptySuites() |
|
968 { |
|
969 // STEP_4. Remove empty suites |
|
970 // Before modifying this function, please see STEP_1 comments in CreatePlanL() |
|
971 |
|
972 // Checking for duplicate is done by checking if suite prepare/finalize |
|
973 // is in the plan next to each other. |
|
974 // |
|
975 // NOTE_4 |
|
976 // After a empty suite is removed, step back one index. |
|
977 // so that the previous item will be re-evaluated, in case removing them cased |
|
978 // the parent suite to be empty as well. |
|
979 // e.g |
|
980 // i == 1 |
|
981 // index: 0 [1] 2 3 |
|
982 // <A <B B> A> |
|
983 // after removal, now prepare/finalize A becomes next to each other |
|
984 // |
|
985 // i == 1 |
|
986 // index: 0 [1] |
|
987 // <A A> |
|
988 // |
|
989 // in order to make sure that above case is handled, decrement i and |
|
990 // re-evaluate from index 0 |
|
991 // |
|
992 TInt i = 0; |
|
993 while ( i < iPlan.Count() - 2 ) // no need to go beyond the last item |
|
994 { |
|
995 if ( iPlan[i]->Type() == CDiagExecPlanEntryImpl::ETypeSuitePrepare && |
|
996 iPlan[i+1]->Type() == CDiagExecPlanEntryImpl::ETypeSuiteFinalize ) |
|
997 { |
|
998 // if these two do not match, then there may have been |
|
999 // a problem during plan creation. |
|
1000 __ASSERT_DEBUG( iPlan[i]->Plugin().Uid() == iPlan[i+1]->Plugin().Uid(), |
|
1001 Panic( EDiagFrameworkCorruptPlugin ) ); |
|
1002 |
|
1003 |
|
1004 CDiagExecPlanEntryImpl* entry = iPlan[ i + 1 ]; |
|
1005 iPlan.Remove( i+1 ); |
|
1006 delete entry; |
|
1007 entry = NULL; |
|
1008 |
|
1009 entry = iPlan[i]; |
|
1010 iPlan.Remove( i ); |
|
1011 delete entry; |
|
1012 entry = NULL; |
|
1013 |
|
1014 // Wondering why step back by one? See NOTE_4 |
|
1015 if ( i > 0 ) |
|
1016 { |
|
1017 i--; |
|
1018 } |
|
1019 } |
|
1020 else |
|
1021 { |
|
1022 // it's not empty. Examine next item. |
|
1023 i++; |
|
1024 } |
|
1025 } |
|
1026 } |
|
1027 |
|
1028 // --------------------------------------------------------------------------- |
|
1029 // CDiagPluginExecPlanImpl::InsertSuiteTransitionsL |
|
1030 // --------------------------------------------------------------------------- |
|
1031 // |
|
1032 void CDiagPluginExecPlanImpl::InsertSuiteTransitionsL() |
|
1033 { |
|
1034 // STEP_5. Add pre/post suite execution based on test parent change. |
|
1035 // Before modifying this function, please see STEP_1 comments in CreatePlanL() |
|
1036 |
|
1037 // if plan is empty, nothing to do. |
|
1038 if ( iPlan.Count() == 0 ) |
|
1039 { |
|
1040 return; |
|
1041 } |
|
1042 |
|
1043 // Create a new CStack. Second template parameter ETrue means that |
|
1044 // CStack owns the stack entries. |
|
1045 CStack<TTransitionStackEntry, ETrue>* stack = |
|
1046 new( ELeave )CStack<TTransitionStackEntry, ETrue>; |
|
1047 |
|
1048 CleanupStack::PushL( stack ); |
|
1049 |
|
1050 // create a root entry |
|
1051 AddRootSuiteIfMissingL(); |
|
1052 |
|
1053 // In this loop, iPlan.Count() cannot be cached because new item may be |
|
1054 // added within the loop |
|
1055 TInt i = 0; |
|
1056 while ( i < iPlan.Count() ) |
|
1057 { |
|
1058 #ifdef _DEBUG_EXEC_PLAN |
|
1059 LOGSTRING2( "CDiagPluginExecPlanImpl::InsertSuiteTransitionsL: ------ %d", i ) |
|
1060 LogPlanL(); |
|
1061 #endif // _DEBUG_EXEC_PLAN |
|
1062 |
|
1063 // Case 1 |
|
1064 // If current item is a suite prepare, push a new level into stack. |
|
1065 if ( iPlan[i]->Type() == CDiagExecPlanEntryImpl::ETypeSuitePrepare ) |
|
1066 { |
|
1067 // we are entering a new suite. Push current plan item into stack. |
|
1068 PushNewLevelL( *stack, i ); |
|
1069 i++; |
|
1070 continue; //lint !e960 continue OK. examine next item. |
|
1071 } |
|
1072 |
|
1073 // Case 2 |
|
1074 // If current item is a suite finalize, pop a level from stack. |
|
1075 if ( iPlan[i]->Type() == CDiagExecPlanEntryImpl::ETypeSuiteFinalize && |
|
1076 stack->Head() != NULL && |
|
1077 stack->Head()->iLevelUid == iPlan[i]->Plugin().Uid() ) |
|
1078 { |
|
1079 // we are leaving a suite. Pop top item from suite. |
|
1080 PopLevel( *stack ); |
|
1081 i++; |
|
1082 continue; //lint !e960 : continue OK. examine next item. |
|
1083 } |
|
1084 |
|
1085 // it was neither prepare or finalize. Examine item as current level. |
|
1086 const TTransitionStackEntry& level = *(stack->Head()); // Peek |
|
1087 |
|
1088 TUid newLevelUid = iPlan[i]->Plugin().ParentUid(); |
|
1089 |
|
1090 // Case 3 |
|
1091 if ( newLevelUid == level.iLevelUid ) |
|
1092 { |
|
1093 // still in the same suite level. No need to add new items. |
|
1094 |
|
1095 // check if current item is non-dependent. |
|
1096 // If so, update the iAsDependent to reflect that it includes |
|
1097 // a non-dependent item. |
|
1098 if ( !(iPlan[i]->AsDependency()) ) |
|
1099 { |
|
1100 // update the prepare item, indicating that it has |
|
1101 // an non-dependent item |
|
1102 iPlan[level.iPrepareIndex]->SetAsDependency( EFalse ); |
|
1103 } |
|
1104 i++; |
|
1105 continue; //lint !e960 : continue OK. examine next item. |
|
1106 } |
|
1107 |
|
1108 // If parent UID is differnt from current level uid, |
|
1109 // it can mean one of the following: |
|
1110 // A ) We are entering a new suite. |
|
1111 // B ) We leaving a suite. |
|
1112 // Case B ) can be deteced by checking whether the new parent is |
|
1113 // already in the stack somewhere (stack will be popped until we are |
|
1114 // in the same level), or if there is no more item of the same |
|
1115 // level is in the plan, which means it is not needed. |
|
1116 // If case B ) fails, assume case A. |
|
1117 if ( IsLevelInStack( *stack, newLevelUid ) || |
|
1118 !IsThisSuiteNeededAfterThisIndex( stack->Head()->iLevelUid, i ) ) |
|
1119 { |
|
1120 // Case B) Insert a new Finalize item. |
|
1121 AddSuiteFinalizeL( level.iPrepareIndex, i ); |
|
1122 } |
|
1123 else |
|
1124 { |
|
1125 // Case A) Insert a new prepare item. |
|
1126 AddSuitePrepareL( newLevelUid, i ); |
|
1127 } |
|
1128 } |
|
1129 |
|
1130 // When all done, stack must be empty. |
|
1131 __ASSERT_DEBUG( stack->IsEmpty(), Panic( EDiagFrameworkInternal ) ); |
|
1132 |
|
1133 CleanupStack::PopAndDestroy( stack ); |
|
1134 stack = NULL; |
|
1135 } |
|
1136 |
|
1137 // --------------------------------------------------------------------------- |
|
1138 // CDiagPluginExecPlanImpl::AddRootSuiteIfMissingL |
|
1139 // --------------------------------------------------------------------------- |
|
1140 // |
|
1141 void CDiagPluginExecPlanImpl::AddRootSuiteIfMissingL() |
|
1142 { |
|
1143 // Check to see if root element is already in the plan. |
|
1144 if ( iPlan[0]->Plugin().Uid() != KDiagRootSuiteUid ) |
|
1145 { |
|
1146 // root( uid 0 ) does not exist in the plan. |
|
1147 // Add prepare and finalize root into the plan. |
|
1148 MDiagPlugin& rootPlugin = iEngine.PluginPool().FindPluginL( KDiagRootSuiteUid ); |
|
1149 |
|
1150 CDiagExecPlanEntryImplSuite* rootEntry = |
|
1151 CDiagExecPlanEntryImplSuite::NewLC( |
|
1152 iEngine, |
|
1153 iEngineConfig, |
|
1154 iPlanEntryObserver, |
|
1155 static_cast< MDiagSuitePlugin& >( rootPlugin ), |
|
1156 ETrue, // iAsDependent == ETrue. Updated as later. |
|
1157 CDiagExecPlanEntryImpl::ETypeSuitePrepare ); |
|
1158 |
|
1159 iPlan.InsertL( static_cast< CDiagExecPlanEntryImpl* >( rootEntry ), 0 ); |
|
1160 CleanupStack::Pop( rootEntry ); // ownership transferred above. |
|
1161 rootEntry = NULL; |
|
1162 |
|
1163 rootEntry = CDiagExecPlanEntryImplSuite::NewLC( |
|
1164 iEngine, |
|
1165 iEngineConfig, |
|
1166 iPlanEntryObserver, |
|
1167 static_cast< MDiagSuitePlugin& >( rootPlugin ), |
|
1168 ETrue, // iAsDependent == ETrue. Updated as later. |
|
1169 CDiagExecPlanEntryImpl::ETypeSuiteFinalize ); |
|
1170 |
|
1171 // insert same entry with finalize as type |
|
1172 iPlan.AppendL( static_cast< CDiagExecPlanEntryImpl* >( rootEntry ) ); |
|
1173 CleanupStack::Pop( rootEntry ); // ownership transferred above |
|
1174 rootEntry = NULL; |
|
1175 } |
|
1176 } |
|
1177 |
|
1178 // --------------------------------------------------------------------------- |
|
1179 // CDiagPluginExecPlanImpl::PushNewLevelL |
|
1180 // --------------------------------------------------------------------------- |
|
1181 // |
|
1182 void CDiagPluginExecPlanImpl::PushNewLevelL( |
|
1183 CStack<TTransitionStackEntry, ETrue>& aStack, |
|
1184 TInt aHeadIndex ) |
|
1185 { |
|
1186 TTransitionStackEntry* level = new( ELeave )TTransitionStackEntry; |
|
1187 |
|
1188 __ASSERT_ALWAYS( aHeadIndex >= 0 && aHeadIndex < iPlan.Count(), |
|
1189 Panic( EDiagFrameworkInternal ) ); |
|
1190 |
|
1191 level->iLevelUid = iPlan[aHeadIndex]->Plugin().Uid(); |
|
1192 level->iPrepareIndex = aHeadIndex; |
|
1193 |
|
1194 #ifdef _DEBUG_EXEC_PLAN |
|
1195 LOGSTRING2( "CDiagPluginExecPlanImpl:: Push 0x%08x", level->iLevelUid.iUid ) |
|
1196 #endif // _DEBUG_EXEC_PLAN |
|
1197 |
|
1198 aStack.PushL( level ); // owership transferred. |
|
1199 level = NULL; //lint !e423 Ownership transferred. No leak here. |
|
1200 } |
|
1201 |
|
1202 // --------------------------------------------------------------------------- |
|
1203 // CDiagPluginExecPlanImpl::PopLevel |
|
1204 // --------------------------------------------------------------------------- |
|
1205 // |
|
1206 void CDiagPluginExecPlanImpl::PopLevel( CStack<TTransitionStackEntry, ETrue>& aStack ) |
|
1207 { |
|
1208 TTransitionStackEntry* level = aStack.Pop(); |
|
1209 #ifdef _DEBUG_EXEC_PLAN |
|
1210 LOGSTRING2( "CDiagPluginExecPlanImpl:: Pop 0x%08x", level->iLevelUid.iUid ) |
|
1211 #endif // _DEBUG_EXEC_PLAN |
|
1212 delete level; |
|
1213 level = NULL; |
|
1214 } |
|
1215 |
|
1216 // --------------------------------------------------------------------------- |
|
1217 // CDiagPluginExecPlanImpl::IsLevelInStack |
|
1218 // --------------------------------------------------------------------------- |
|
1219 // |
|
1220 TBool CDiagPluginExecPlanImpl::IsLevelInStack( |
|
1221 CStack<TTransitionStackEntry, ETrue>& aStack, |
|
1222 TUid aLevelUid ) const |
|
1223 { |
|
1224 for ( TInt i = 0; i < aStack.Count(); i++ ) |
|
1225 { |
|
1226 const TTransitionStackEntry& currEntry = *aStack[i]; |
|
1227 if ( currEntry.iLevelUid == aLevelUid ) |
|
1228 { |
|
1229 return ETrue; |
|
1230 } |
|
1231 } |
|
1232 |
|
1233 return EFalse; |
|
1234 } |
|
1235 |
|
1236 // --------------------------------------------------------------------------- |
|
1237 // CDiagPluginExecPlanImpl::IsThisSuiteNeededAfterThisIndex |
|
1238 // --------------------------------------------------------------------------- |
|
1239 // |
|
1240 TBool CDiagPluginExecPlanImpl::IsThisSuiteNeededAfterThisIndex( |
|
1241 TUid aSuiteUid, |
|
1242 TInt aIndex ) const |
|
1243 { |
|
1244 for ( TInt i = aIndex; i < iPlan.Count(); i++ ) |
|
1245 { |
|
1246 if ( iPlan[i]->Plugin().Uid() == aSuiteUid || // finalize already exists |
|
1247 iPlan[i]->Plugin().ParentUid() == aSuiteUid ) |
|
1248 { |
|
1249 return ETrue; |
|
1250 } |
|
1251 } |
|
1252 |
|
1253 return EFalse; |
|
1254 } |
|
1255 |
|
1256 // --------------------------------------------------------------------------- |
|
1257 // CDiagPluginExecPlanImpl::AddSuitePrepareL |
|
1258 // --------------------------------------------------------------------------- |
|
1259 // |
|
1260 void CDiagPluginExecPlanImpl::AddSuitePrepareL( TUid aLevelUid, TInt aAt ) |
|
1261 { |
|
1262 MDiagPlugin& suitePlugin = iEngine.PluginPool().FindPluginL( aLevelUid ); |
|
1263 |
|
1264 CDiagExecPlanEntryImplSuite* prepareEntry = |
|
1265 CDiagExecPlanEntryImplSuite::NewLC( |
|
1266 iEngine, |
|
1267 iEngineConfig, |
|
1268 iPlanEntryObserver, |
|
1269 static_cast< MDiagSuitePlugin& >( suitePlugin ), |
|
1270 ETrue, // iAsDependent. Updated as later if not true. |
|
1271 CDiagExecPlanEntryImpl::ETypeSuitePrepare ); |
|
1272 |
|
1273 iPlan.InsertL( static_cast< CDiagExecPlanEntryImpl* >( prepareEntry ), aAt ); |
|
1274 CleanupStack::Pop( prepareEntry ); // ownership transfer |
|
1275 prepareEntry = NULL; |
|
1276 |
|
1277 #ifdef _DEBUG_EXEC_PLAN |
|
1278 LOGSTRING2( "CDiagPluginExecPlanImpl:: InsertPrepare 0x%08x", aLevelUid ) |
|
1279 #endif // _DEBUG_EXEC_PLAN |
|
1280 } |
|
1281 |
|
1282 // --------------------------------------------------------------------------- |
|
1283 // CDiagPluginExecPlanImpl::AddSuiteFinalizeL |
|
1284 // --------------------------------------------------------------------------- |
|
1285 // |
|
1286 void CDiagPluginExecPlanImpl::AddSuiteFinalizeL( TInt aPrepareIndex, TInt aAt ) |
|
1287 { |
|
1288 // It is identical to the prepare entry, except that type is ETypeSuiteFinalize |
|
1289 __ASSERT_ALWAYS( aPrepareIndex >= 0 && aPrepareIndex < iPlan.Count(), |
|
1290 Panic( EDiagFrameworkInternal ) ); |
|
1291 |
|
1292 CDiagExecPlanEntryImplSuite& prepareEntry = |
|
1293 static_cast< CDiagExecPlanEntryImplSuite& > ( *(iPlan[aPrepareIndex]) ); |
|
1294 |
|
1295 CDiagExecPlanEntryImplSuite* finalizeEntry = |
|
1296 CDiagExecPlanEntryImplSuite::NewLC( |
|
1297 iEngine, |
|
1298 iEngineConfig, |
|
1299 iPlanEntryObserver, |
|
1300 prepareEntry.SuitePlugin(), |
|
1301 prepareEntry.AsDependency(), |
|
1302 CDiagExecPlanEntryImpl::ETypeSuiteFinalize ); |
|
1303 |
|
1304 iPlan.InsertL( static_cast< CDiagExecPlanEntryImpl* >( finalizeEntry ), aAt ); |
|
1305 CleanupStack::Pop( finalizeEntry ); // ownership transmitted above |
|
1306 finalizeEntry = NULL; |
|
1307 |
|
1308 #ifdef _DEBUG_EXEC_PLAN |
|
1309 LOGSTRING2( "CDiagPluginExecPlanImpl:: InsertFinalize 0x%08x", prepareEntry.Plugin().Uid().iUid ); |
|
1310 #endif // _DEBUG_EXEC_PLAN |
|
1311 } |
|
1312 |
|
1313 // --------------------------------------------------------------------------- |
|
1314 // CDiagPluginExecPlanImpl::StoreNextTestPluginToDbL |
|
1315 // --------------------------------------------------------------------------- |
|
1316 // |
|
1317 void CDiagPluginExecPlanImpl::StoreNextTestPluginToDbL() |
|
1318 { |
|
1319 // STEP_6. Store plan to DB. |
|
1320 // In this step, all test entries must be stored in db with EQueuedToRun |
|
1321 // status. Since DbRecord().LogTestResult() is an async call, only one |
|
1322 // item can be written at a time. |
|
1323 // |
|
1324 // To do this, this function will search for the next "TEST" plug-in that |
|
1325 // needs to be logged to DB. Once it is found, it will call async function |
|
1326 // LogTestResult() and wait for RunL() to execute again. |
|
1327 // In RunL(), StoreNextTestPluginToDbL() is called again, and it will look for the |
|
1328 // next test plugin to store until it loops through all items in plan. |
|
1329 while ( MoveCursorToNext() ) |
|
1330 { |
|
1331 if ( CurrentExecutionItem().Plugin().Type() == MDiagPlugin::ETypeTestPlugin ) |
|
1332 { |
|
1333 LOGSTRING2( "CDiagPluginExecPlanImpl::RunL: STEP_6 - storing item 0x%08x", |
|
1334 CurrentExecutionItem().Plugin().Uid().iUid ) |
|
1335 |
|
1336 CDiagResultsDatabaseItem* resultItem = |
|
1337 CDiagResultsDbItemBuilder::CreateSimpleDbItemL( |
|
1338 CurrentExecutionItem().Plugin().Uid(), |
|
1339 CurrentExecutionItem().AsDependency(), |
|
1340 CDiagResultsDatabaseItem::EQueuedToRun ); |
|
1341 |
|
1342 // Record initial test result to db. |
|
1343 // StoreNextTestPluginToDbL() will be called again later from RunL() |
|
1344 iEngine.DbRecord().LogTestResult( iStatus, *resultItem ); |
|
1345 SetActive(); |
|
1346 |
|
1347 delete resultItem; |
|
1348 resultItem = NULL; |
|
1349 |
|
1350 // Exit here since we must wait for LogTestResult() to complete |
|
1351 // before moving on to the next item. |
|
1352 return; |
|
1353 } |
|
1354 } |
|
1355 |
|
1356 // All items are stored now. |
|
1357 ChangeState( EStatePlanCreated ); |
|
1358 } |
|
1359 |
|
1360 // --------------------------------------------------------------------------- |
|
1361 // CDiagPluginExecPlanImpl::PrependExecutedItemsL |
|
1362 // --------------------------------------------------------------------------- |
|
1363 // |
|
1364 void CDiagPluginExecPlanImpl::PrependExecutedItemsL() |
|
1365 { |
|
1366 #ifdef _DEBUG_EXEC_PLAN |
|
1367 LOGSTRING( "CDiagExecPlanEntryImpl::PrependExecutedItemsL(). " |
|
1368 L" Before prepending executed entries" ); |
|
1369 LogPlanL(); |
|
1370 #endif // _DEBUG_EXEC_PLAN |
|
1371 |
|
1372 for ( TInt lastIndex = iExecutedEntries.Count() - 1; |
|
1373 lastIndex >= 0 ; |
|
1374 lastIndex-- ) |
|
1375 { |
|
1376 // Insert last entry from the executed list to the beginning. |
|
1377 iPlan.InsertL( iExecutedEntries[ lastIndex ], 0 ); |
|
1378 iExecutedEntries.Remove( lastIndex ); |
|
1379 } |
|
1380 } |
|
1381 |
|
1382 // --------------------------------------------------------------------------- |
|
1383 // CDiagPluginExecPlanImpl::ReportResult |
|
1384 // --------------------------------------------------------------------------- |
|
1385 // |
|
1386 void CDiagPluginExecPlanImpl::ReportResult( TInt aError ) |
|
1387 { |
|
1388 User::RequestComplete( iClientStatus, aError ); |
|
1389 iClientStatus = NULL; |
|
1390 } |
|
1391 |
|
1392 // --------------------------------------------------------------------------- |
|
1393 // CDiagPluginExecPlanImpl::InsertPluginL |
|
1394 // --------------------------------------------------------------------------- |
|
1395 // |
|
1396 TBool CDiagPluginExecPlanImpl::InsertPluginL( MDiagPlugin& aPlugin, |
|
1397 TBool aAsDependency, |
|
1398 TInt aAt ) |
|
1399 { |
|
1400 #ifdef _DEBUG_EXEC_PLAN |
|
1401 LOGSTRING4( "CDiagPluginExecPlanImpl::InsertPluginL:" |
|
1402 L"Id = 0x%x, Type = %s, At %d", |
|
1403 aPlugin.Uid().iUid, |
|
1404 ( aPlugin.Type() == MDiagPlugin::ETypeTestPlugin ? L"Test" : L"Suite" ), |
|
1405 aAt ) |
|
1406 #endif // _DEBUG_EXEC_PLAN |
|
1407 |
|
1408 __ASSERT_ALWAYS( aAt >= 0 && aAt <= iPlan.Count(), Panic( EDiagFrameworkArrayBounds ) ); |
|
1409 |
|
1410 // First, examine items before given index. |
|
1411 // If new item has iAsDependent == ETrue, and also found before the given index, |
|
1412 // --> it is okay to not insert the item, since it will just be duplicates. |
|
1413 // if new item has iAsDependent == EFalse, |
|
1414 // --> no need to check for items prior to current position, since |
|
1415 // explicit |
|
1416 // where it was requested. |
|
1417 TInt idx = 0; |
|
1418 if ( aAsDependency ) |
|
1419 { |
|
1420 // check if it was already executed in the previous session. |
|
1421 for ( idx = 0; idx < iExecutedEntries.Count(); idx++ ) |
|
1422 { |
|
1423 if ( iExecutedEntries[idx]->Plugin().Uid() == aPlugin.Uid() ) |
|
1424 { |
|
1425 // matching item found. |
|
1426 // No need to instert a new item. |
|
1427 return EFalse; |
|
1428 } |
|
1429 } |
|
1430 |
|
1431 // check for items in current plan. |
|
1432 for ( idx = 0; idx < aAt && idx < iPlan.Count(); idx++ ) |
|
1433 { |
|
1434 if ( iPlan[idx]->Plugin().Uid() == aPlugin.Uid() ) |
|
1435 { |
|
1436 // Matching item found. |
|
1437 // No change to plan made. |
|
1438 return EFalse; |
|
1439 } |
|
1440 } |
|
1441 } |
|
1442 |
|
1443 // Duplicate item not found before given index. |
|
1444 // An item will be inserted at the given index. Now, we search for |
|
1445 // duplicates after current index, and see if we can remove them. |
|
1446 idx = aAt; |
|
1447 while ( idx < iPlan.Count() ) |
|
1448 { |
|
1449 if ( iPlan[idx]->Plugin().Uid() == aPlugin.Uid() && iPlan[idx]->AsDependency() ) |
|
1450 { |
|
1451 // Item is found, and it was for dependency. |
|
1452 // We can move this item to current position. |
|
1453 // For now, we just need to remove it, since it will be added at |
|
1454 // current position when for loop is done. |
|
1455 CDiagExecPlanEntryImpl* entry = iPlan[idx]; |
|
1456 iPlan.Remove( idx ); |
|
1457 delete entry; |
|
1458 entry = NULL; |
|
1459 |
|
1460 // no need to increment idx, since current item is removed. |
|
1461 // idx should already be at the next item. |
|
1462 } |
|
1463 else |
|
1464 { |
|
1465 idx++; // check next item. |
|
1466 } |
|
1467 } |
|
1468 |
|
1469 // Either plug-in is not found, or we found one that we can move. |
|
1470 // Add to current position. |
|
1471 CDiagExecPlanEntryImpl* newEntry = CreateDefaultPlanEntryLC( |
|
1472 aPlugin, |
|
1473 aAsDependency ); |
|
1474 |
|
1475 iPlan.InsertL( newEntry, aAt ); |
|
1476 CleanupStack::Pop( newEntry ); |
|
1477 newEntry = NULL; |
|
1478 |
|
1479 return ETrue; |
|
1480 } |
|
1481 |
|
1482 // --------------------------------------------------------------------------- |
|
1483 // CDiagPluginExecPlanImpl::CreateDefaultPlanEntryL |
|
1484 // |
|
1485 // --------------------------------------------------------------------------- |
|
1486 // |
|
1487 CDiagExecPlanEntryImpl* CDiagPluginExecPlanImpl::CreateDefaultPlanEntryLC( |
|
1488 MDiagPlugin& aPlugin, |
|
1489 TBool aAsDependency ) const |
|
1490 { |
|
1491 CDiagExecPlanEntryImpl* newEntry = NULL; |
|
1492 |
|
1493 if ( aPlugin.Type() == MDiagPlugin::ETypeTestPlugin ) |
|
1494 { |
|
1495 newEntry = static_cast< CDiagExecPlanEntryImpl* >( |
|
1496 CDiagExecPlanEntryImplTest::NewLC( |
|
1497 iEngine, |
|
1498 iEngineConfig, |
|
1499 iPlanEntryObserver, |
|
1500 static_cast< MDiagTestPlugin& >( aPlugin ), |
|
1501 aAsDependency, |
|
1502 CDiagResultsDatabaseItem::EQueuedToRun ) ); |
|
1503 } |
|
1504 else |
|
1505 { |
|
1506 newEntry = static_cast< CDiagExecPlanEntryImpl* >( |
|
1507 CDiagExecPlanEntryImplSuite::NewLC( |
|
1508 iEngine, |
|
1509 iEngineConfig, |
|
1510 iPlanEntryObserver, |
|
1511 static_cast< MDiagSuitePlugin& >( aPlugin ), |
|
1512 aAsDependency, |
|
1513 CDiagExecPlanEntryImpl::ETypeSuiteUnexpanded ) ); |
|
1514 } |
|
1515 |
|
1516 return newEntry; |
|
1517 } |
|
1518 |
|
1519 // --------------------------------------------------------------------------- |
|
1520 // CDiagPluginExecPlanImpl::LogPlan |
|
1521 // --------------------------------------------------------------------------- |
|
1522 // |
|
1523 void CDiagPluginExecPlanImpl::LogPlanL() const |
|
1524 { |
|
1525 #ifdef _DEBUG |
|
1526 LOGSTRING( "CDiagPluginExecPlanImpl::LogPlan(): Plan Dump." ) |
|
1527 for ( TInt i = 0; i < iPlan.Count(); i++ ) |
|
1528 { |
|
1529 HBufC* pluginName = iPlan[i]->Plugin().GetPluginNameL( |
|
1530 MDiagPlugin::ENameLayoutListSingle ); |
|
1531 |
|
1532 LOGSTRING5( "Plan Entry: Id = 0x%08x, %s, Dep=[%s], Name = %S", |
|
1533 iPlan[i]->Plugin().Uid().iUid, |
|
1534 ( iPlan[i]->Type() == CDiagExecPlanEntryImpl::ETypeSuitePrepare ? L"<" : |
|
1535 ( iPlan[i]->Type() == CDiagExecPlanEntryImpl::ETypeSuiteFinalize ? L">" : L" " ) ), |
|
1536 ( iPlan[i]->AsDependency() ? L"*" : L" " ), |
|
1537 pluginName ) |
|
1538 |
|
1539 delete pluginName; |
|
1540 } |
|
1541 #endif // _DEBUG |
|
1542 } |
|
1543 |
|
1544 // --------------------------------------------------------------------------- |
|
1545 // CDiagPluginExecPlanImpl::LogPlanInRecordL |
|
1546 // --------------------------------------------------------------------------- |
|
1547 // |
|
1548 void CDiagPluginExecPlanImpl::LogPlanInRecordL() const |
|
1549 { |
|
1550 #ifdef _DEBUG |
|
1551 |
|
1552 LOGSTRING( "CDiagPluginExecPlanImpl::LogPlanInRecord()" ) |
|
1553 |
|
1554 RPointerArray< CDiagResultsDatabaseItem > results; |
|
1555 DiagFwInternal::CleanupRPointerArrayPushL< CDiagResultsDatabaseItem >( &results ); |
|
1556 User::LeaveIfError( |
|
1557 iEngine.DbRecord().GetTestResults( results ) ); |
|
1558 |
|
1559 TInt resultCount = results.Count(); |
|
1560 |
|
1561 LOGSTRING2( " Result Count = %d", resultCount ) |
|
1562 |
|
1563 for ( TInt i = 0; i < resultCount; i++ ) |
|
1564 { |
|
1565 LOGSTRING4( " Test UID = 0x%08x, Result = %d, Dep = %d", |
|
1566 results[i]->TestUid().iUid, |
|
1567 results[i]->TestResult(), |
|
1568 results[i]->WasDependency() ) |
|
1569 } |
|
1570 |
|
1571 CleanupStack::PopAndDestroy( &results ); |
|
1572 |
|
1573 #endif // _DEBUG |
|
1574 } |
|
1575 |
|
1576 // End of File |
|
1577 |
|