|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @test |
|
19 @internalComponent - Internal Symbian test code |
|
20 */ |
|
21 |
|
22 |
|
23 #include <ssm/ssmcommandlist.h> |
|
24 |
|
25 #include "ssmswppolicyframe.h" |
|
26 #include "ssmswptransitionengine.h" |
|
27 |
|
28 #include "ssmatest_utils.h" |
|
29 #include "tssm_step_swptransitionengine.h" |
|
30 #include "tssm_swppolicy_generic.h" |
|
31 #include "tssm_swppolicy_generic.hrh" |
|
32 |
|
33 #include <e32debug.h> |
|
34 |
|
35 // Keys and values used for testing the transition engines |
|
36 static const TUint KSwpTestKey1 = 0xE5325221; |
|
37 |
|
38 const TInt KTestErrorBadCategory = -911; |
|
39 const TInt KTestErrorBadFunction = -912; |
|
40 |
|
41 /** |
|
42 */ |
|
43 static TInt StopScheduler(TAny* aSsmSwpTransitionEngineTest) |
|
44 { |
|
45 CSsmSwpTransitionEngineTest* ssmSwpRequestEngineTest = static_cast<CSsmSwpTransitionEngineTest*>(aSsmSwpTransitionEngineTest); |
|
46 ssmSwpRequestEngineTest->StopActiveScheduler(); |
|
47 return KErrNone; |
|
48 } |
|
49 |
|
50 //--------------------- Thread creation framework --------------------- |
|
51 |
|
52 /** |
|
53 Test framework to check for panic scenarios |
|
54 It requires to create a separate thread so we can check the panic category and code. |
|
55 */ |
|
56 TInt StartTestInThreadL(TInt aFunction) |
|
57 { |
|
58 RThread thread; |
|
59 // Give each thread a unique name to avoid KErrAlreadyExists error on thread creation |
|
60 _LIT(KThreadNamePrefix, "SsmTestThread"); |
|
61 RBuf threadName; |
|
62 CleanupClosePushL(threadName); |
|
63 threadName.CreateL(KThreadNamePrefix().Length() + 4); // 4 digit thread number |
|
64 threadName = KThreadNamePrefix; |
|
65 threadName.AppendNumFixedWidth(aFunction, EDecimal, 4); |
|
66 const TInt KMinHeapSize = 0xc800; // 50k - NOTE just an arbitrary value, please feel free to change it |
|
67 const TInt KMaxHeapSize = 0x19000; // 100k - NOTE just an arbitrary value, please feel free to change it |
|
68 User::LeaveIfError(thread.Create(threadName, ThreadStartFn, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, (TAny*)aFunction)); |
|
69 CleanupStack::PopAndDestroy(&threadName); |
|
70 TRequestStatus status; |
|
71 thread.Logon(status); |
|
72 TBool jit = User::JustInTime(); |
|
73 User::SetJustInTime(EFalse); |
|
74 thread.Resume(); |
|
75 User::WaitForRequest(status); |
|
76 |
|
77 // always expecting a transition engine panic |
|
78 TExitCategoryName category = thread.ExitCategory(); |
|
79 RDebug::Print(_L("***** Exit Category = %S *****"),&category); |
|
80 if (category.Compare(KPanicSysStateMgr) != 0) |
|
81 { |
|
82 User::Leave(KTestErrorBadCategory); |
|
83 } |
|
84 const TInt exitReason = thread.ExitReason(); |
|
85 thread.Close(); |
|
86 User::SetJustInTime(jit); |
|
87 |
|
88 // return the exit reason for the caller to verify the expected panic value |
|
89 return exitReason; |
|
90 } |
|
91 |
|
92 TInt ThreadStartFn(TAny* aPtr) |
|
93 { |
|
94 CTrapCleanup* trapCleanup = CTrapCleanup::New(); |
|
95 if (!trapCleanup) |
|
96 { |
|
97 return KErrNoMemory; |
|
98 } |
|
99 |
|
100 TInt function = (TInt)aPtr; |
|
101 TRAPD(err, ThreadDispatchFunctionL(function)); |
|
102 |
|
103 delete trapCleanup; |
|
104 return err; |
|
105 } |
|
106 |
|
107 |
|
108 void ThreadDispatchFunctionL(TInt aFunction) |
|
109 { |
|
110 switch (aFunction) |
|
111 { |
|
112 case EThreadSubmitTwice: |
|
113 ThreadSubmitTwiceL(); |
|
114 break; |
|
115 default: |
|
116 User::Leave(KTestErrorBadFunction); |
|
117 break; |
|
118 } |
|
119 } |
|
120 |
|
121 |
|
122 void ThreadSubmitTwiceL() |
|
123 { |
|
124 CSsmSwpTransitionEngineTest* step = new (ELeave) CSsmSwpTransitionEngineTest(); |
|
125 |
|
126 CActiveScheduler* activeScheduler = new(ELeave) CActiveScheduler; |
|
127 CleanupStack::PushL(activeScheduler); |
|
128 CActiveScheduler::Install(activeScheduler); |
|
129 |
|
130 CAsyncCallBack* asyncStopScheduler = new(ELeave) CAsyncCallBack(CActive::EPriorityIdle); |
|
131 TCallBack stop(StopScheduler, step); |
|
132 asyncStopScheduler->Set(stop); |
|
133 CleanupStack::Pop(activeScheduler); |
|
134 |
|
135 // ssmswppolicyproxy is created and set by the individualtransitionscheduler, since |
|
136 // we are submitting the request directly to the engine the ssmswppolicyproxy should be |
|
137 // created and set in the engine |
|
138 CSsmSwpPolicyCliSession* ssmSwpPolicySession = CSsmSwpPolicyCliSession::NewL(); |
|
139 CleanupStack::PushL(ssmSwpPolicySession); |
|
140 |
|
141 // Setting the cle session as we have to execute the publishswp command. |
|
142 // published swp value is used to stop the scheduler. |
|
143 CCleSessionProxy* cleSession = CCleSessionProxy::NewL(); |
|
144 CleanupStack::PushL(cleSession); |
|
145 |
|
146 const TSsmSwp swpValue(KSwpTestKey1, ESwpGenericDoNothing); |
|
147 CSsmSwpPolicyFrame* policy = step->GetSwpPolicyL(swpValue); |
|
148 CleanupStack::PushL(policy); |
|
149 |
|
150 CSsmSwpTransitionEngine* engine = CSsmSwpTransitionEngine::NewL(swpValue); |
|
151 engine->SetCleSessionProxy(cleSession); |
|
152 engine->SetSwpPolicyFrame(policy); |
|
153 engine->SetSsmSwpPolicySession(ssmSwpPolicySession); |
|
154 CleanupStack::Pop(policy); |
|
155 |
|
156 CleanupStack::PushL(engine); |
|
157 engine->Submit(); |
|
158 engine->Submit(); |
|
159 // etc, etc, etc.. |
|
160 // don't bother to continue here. All being well the second SubmitL will cause a panic! |
|
161 //Cleanup test |
|
162 CleanupStack::PopAndDestroy(3, ssmSwpPolicySession); // and engine |
|
163 } |
|
164 |
|
165 |
|
166 //----------------- CTestStep implemenation -------------------- |
|
167 |
|
168 /** |
|
169 */ |
|
170 CSsmSwpTransitionEngineTest::~CSsmSwpTransitionEngineTest() |
|
171 { |
|
172 iProperty.Close(); |
|
173 delete iAsyncStopScheduler; |
|
174 delete iActiveScheduler; |
|
175 } |
|
176 |
|
177 /** |
|
178 */ |
|
179 CSsmSwpTransitionEngineTest::CSsmSwpTransitionEngineTest() |
|
180 { |
|
181 SetTestStepName(KTSsmSwpTransitionEngineStep); |
|
182 } |
|
183 |
|
184 /** |
|
185 */ |
|
186 TVerdict CSsmSwpTransitionEngineTest::doTestStepPreambleL() |
|
187 { |
|
188 iActiveScheduler = new(ELeave) CActiveScheduler; |
|
189 CActiveScheduler::Install (iActiveScheduler); |
|
190 |
|
191 iAsyncStopScheduler = new(ELeave) CAsyncCallBack(CActive::EPriorityIdle); |
|
192 TCallBack stop(StopScheduler, this); |
|
193 iAsyncStopScheduler->Set(stop); |
|
194 |
|
195 return CTestStep::doTestStepPreambleL(); |
|
196 } |
|
197 |
|
198 /** |
|
199 Old Test CaseID APPFWK-SSM-0007 |
|
200 New Test CaseID DEVSRVS-SSMA-SSM-0007 |
|
201 */ |
|
202 |
|
203 TVerdict CSsmSwpTransitionEngineTest::doTestStepL() |
|
204 { |
|
205 INFO_PRINTF1(_L("CSsmSwpTransitionEngineTest started....")); |
|
206 |
|
207 __UHEAP_MARK; |
|
208 |
|
209 doTestSwpTransitionEngineTestForMemoryLeaksL(); |
|
210 doTestRequestSimpleL(); |
|
211 doTestRequestCancelL(); |
|
212 doTestRequestSubmitTwiceL(); |
|
213 |
|
214 __UHEAP_MARKEND; |
|
215 |
|
216 INFO_PRINTF1(_L("....CSsmSwpTransitionEngineTest completed!!")); |
|
217 return TestStepResult(); |
|
218 } |
|
219 |
|
220 /** |
|
221 */ |
|
222 TVerdict CSsmSwpTransitionEngineTest::doTestStepPostambleL() |
|
223 { |
|
224 return CTestStep::doTestStepPostambleL(); |
|
225 } |
|
226 |
|
227 /** |
|
228 */ |
|
229 void CSsmSwpTransitionEngineTest::doTestSwpTransitionEngineTestForMemoryLeaksL() |
|
230 { |
|
231 INFO_PRINTF1(_L("Checking for destructor memoryleaks in CSsmSwpTransitionEngine")); |
|
232 |
|
233 __UHEAP_MARK; |
|
234 |
|
235 // ssmswppolicyproxy is created and set by the individualtransitionscheduler, since |
|
236 // we are submitting the request directly to the engine the ssmswppolicyproxy should be |
|
237 // created and set in the engine |
|
238 CSsmSwpPolicyCliSession* ssmSwpPolicySession = CSsmSwpPolicyCliSession::NewL(); |
|
239 CleanupStack::PushL(ssmSwpPolicySession); |
|
240 |
|
241 // Setting the cle session as we have to execute the publishswp command. |
|
242 // published swp value is used to stop the scheduler. |
|
243 CCleSessionProxy* cleSession = CCleSessionProxy::NewL(); |
|
244 CleanupStack::PushL(cleSession); |
|
245 |
|
246 const TSsmSwp swpValue(KSwpTestKey1, ESwpGenericDoNothing); |
|
247 CSsmSwpPolicyFrame* policy = this->GetSwpPolicyL(swpValue); |
|
248 CleanupStack::PushL(policy); |
|
249 |
|
250 CSsmSwpTransitionEngine* engine = CSsmSwpTransitionEngine::NewL(swpValue); |
|
251 engine->SetCleSessionProxy(cleSession); |
|
252 engine->SetSwpPolicyFrame(policy); |
|
253 engine->SetSsmSwpPolicySession(ssmSwpPolicySession); |
|
254 CleanupStack::Pop(policy); |
|
255 |
|
256 //Cleanup test |
|
257 CleanupStack::PopAndDestroy(2, ssmSwpPolicySession); |
|
258 delete engine; |
|
259 |
|
260 __UHEAP_MARKEND; |
|
261 } |
|
262 |
|
263 /** |
|
264 Takes CSsmSwpTransitionEngine through the simple swp transition. |
|
265 */ |
|
266 void CSsmSwpTransitionEngineTest::doTestRequestSimpleL() |
|
267 { |
|
268 INFO_PRINTF1(_L("Checking requesthandler with a single request")); |
|
269 |
|
270 __UHEAP_MARK; |
|
271 |
|
272 // ssmswppolicyproxy is created and set by the individualtransitionscheduler, but |
|
273 // we are submitting the request directly to the engine the ssmswppolicyproxy should be |
|
274 // created and set in the engine |
|
275 CSsmSwpPolicyCliSession* ssmSwpPolicySession = CSsmSwpPolicyCliSession::NewL(); |
|
276 CleanupStack::PushL(ssmSwpPolicySession); |
|
277 |
|
278 // Setting the cle session as we have to execute the publishswp command. |
|
279 // published swp value is used to stop the scheduler. |
|
280 CCleSessionProxy* cleSession = CCleSessionProxy::NewL(); |
|
281 CleanupStack::PushL(cleSession); |
|
282 |
|
283 // Define and set the rproperty |
|
284 TEST(KErrNone == iProperty.Define(RProcess().SecureId(), KSwpTestKey1, RProperty::EInt)); |
|
285 TEST(KErrNone == iProperty.Set(RProcess().SecureId(), KSwpTestKey1, 0)); |
|
286 |
|
287 TInt value; |
|
288 TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); |
|
289 TEST(value == 0); |
|
290 |
|
291 const TSsmSwp swpValue(KSwpTestKey1, ESwpGenericDoNothing); |
|
292 CSsmSwpPolicyFrame* policy = this->GetSwpPolicyL(swpValue); |
|
293 CleanupStack::PushL(policy); |
|
294 |
|
295 CSsmSwpTransitionEngine* engine = CSsmSwpTransitionEngine::NewL(swpValue); |
|
296 engine->SetCleSessionProxy(cleSession); |
|
297 engine->SetSwpPolicyFrame(policy); |
|
298 engine->SetSsmSwpPolicySession(ssmSwpPolicySession); |
|
299 engine->PerformCommandListValidation(EFalse); |
|
300 CleanupStack::Pop(policy); |
|
301 |
|
302 CleanupStack::PushL(engine); |
|
303 engine->Submit(); |
|
304 |
|
305 //this callback will not run until the test is finished because it has priority idle |
|
306 iAsyncStopScheduler->CallBack(); |
|
307 //run engine |
|
308 iActiveScheduler->Start(); |
|
309 |
|
310 TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); |
|
311 TEST(value == ESwpGenericDoNothing); |
|
312 |
|
313 TEST(KErrNone == iProperty.Delete(RProcess().SecureId(), KSwpTestKey1)); |
|
314 |
|
315 //Cleanup test |
|
316 CleanupStack::PopAndDestroy(3, ssmSwpPolicySession); // and engine |
|
317 |
|
318 __UHEAP_MARKEND; |
|
319 } |
|
320 |
|
321 /** |
|
322 Takes CSsmSwpTransitionEngine through the simple swp transition and cancels it. |
|
323 */ |
|
324 void CSsmSwpTransitionEngineTest::doTestRequestCancelL() |
|
325 { |
|
326 INFO_PRINTF1(_L("Checking requesthandler with a cancel request")); |
|
327 |
|
328 __UHEAP_MARK; |
|
329 |
|
330 // ssmswppolicyproxy is created and set by the individualtransitionscheduler, but |
|
331 // we are submitting the request directly to the engine the ssmswppolicyproxy should be |
|
332 // created and set in the engine |
|
333 CSsmSwpPolicyCliSession* ssmSwpPolicySession = CSsmSwpPolicyCliSession::NewL(); |
|
334 CleanupStack::PushL(ssmSwpPolicySession); |
|
335 |
|
336 // Setting the cle session as we have to execute the publishswp command. |
|
337 // published swp value is used to stop the scheduler. |
|
338 CCleSessionProxy* cleSession = CCleSessionProxy::NewL(); |
|
339 CleanupStack::PushL(cleSession); |
|
340 |
|
341 // Define and set the rproperty |
|
342 TEST(KErrNone == iProperty.Define(RProcess().SecureId(), KSwpTestKey1, RProperty::EInt)); |
|
343 TEST(KErrNone == iProperty.Set(RProcess().SecureId(), KSwpTestKey1, -5)); |
|
344 |
|
345 TInt value; |
|
346 TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); |
|
347 TEST(value == -5); |
|
348 |
|
349 const TSsmSwp swpValue(KSwpTestKey1, ESwpGenericDoNothing); |
|
350 CSsmSwpPolicyFrame* policy = this->GetSwpPolicyL(swpValue); |
|
351 CleanupStack::PushL(policy); |
|
352 |
|
353 CSsmSwpTransitionEngine* engine = CSsmSwpTransitionEngine::NewL(swpValue); |
|
354 engine->SetCleSessionProxy(cleSession); |
|
355 engine->SetSwpPolicyFrame(policy); |
|
356 engine->SetSsmSwpPolicySession(ssmSwpPolicySession); |
|
357 engine->PerformCommandListValidation(EFalse); |
|
358 CleanupStack::Pop(policy); |
|
359 |
|
360 CleanupStack::PushL(engine); |
|
361 engine->Submit(); |
|
362 engine->Cancel(); |
|
363 |
|
364 //this callback will not run until the test is finished because it has priority idle |
|
365 iAsyncStopScheduler->CallBack(); |
|
366 //run engine |
|
367 iActiveScheduler->Start(); |
|
368 |
|
369 TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); |
|
370 TEST(value == -5); |
|
371 |
|
372 TEST(KErrNone == iProperty.Delete(RProcess().SecureId(), KSwpTestKey1)); |
|
373 |
|
374 //Cleanup test |
|
375 CleanupStack::PopAndDestroy(3, ssmSwpPolicySession); // and engine |
|
376 |
|
377 __UHEAP_MARKEND; |
|
378 } |
|
379 |
|
380 void CSsmSwpTransitionEngineTest::doTestRequestSubmitTwiceL() |
|
381 { |
|
382 INFO_PRINTF1(_L("Checking requesthandler with two consecutive requests")); |
|
383 TInt exitReason(0); |
|
384 TRAPD(err, exitReason = StartTestInThreadL(EThreadSubmitTwice)); |
|
385 TEST(err == KErrNone); |
|
386 INFO_PRINTF2(_L(" 3-- StartTestInThreadL method completed with '%d'."), err); |
|
387 TEST(exitReason == ESwpTransitionEngineError3); |
|
388 INFO_PRINTF3(_L(" 3-- received panic '%d', expected was '%d'."), exitReason, ESwpTransitionEngineError3); |
|
389 |
|
390 // this test raises panics due to negative testing - close them to clear the screen. |
|
391 CloseAllPanicWindowsL(); |
|
392 } |
|
393 |
|
394 void CSsmSwpTransitionEngineTest::StopActiveScheduler() |
|
395 { |
|
396 // We would stop the sceduler once all the required transitions are completed |
|
397 //Verify that the expected calls were made |
|
398 TInt value; |
|
399 TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); |
|
400 |
|
401 // We have to stop the scheduler in case of Cancel test code, so testing property's initial value. |
|
402 if (value == ESwpGenericDoNothing || value == -5) |
|
403 { |
|
404 CActiveScheduler::Stop(); |
|
405 } |
|
406 else |
|
407 { |
|
408 iAsyncStopScheduler->CallBack(); |
|
409 } |
|
410 } |
|
411 |
|
412 //----------------- MPolicyResolverProxy implementation -------------------- |
|
413 |
|
414 CSsmSwpPolicyFrame* CSsmSwpTransitionEngineTest::CreatePolicyLC(const RLibrary& aLibrary) const |
|
415 { |
|
416 __ASSERT_DEBUG( KNullHandle != aLibrary.Handle(), PanicNow(KPanicSysStateMgr, ESwpPolicyResolverLibraryNotLoaded)); |
|
417 |
|
418 CSsmSwpPolicyFrame* frame = NULL; |
|
419 TRAPD(err, frame = CSsmSwpPolicyFrame::NewL(aLibrary.Lookup(1))); |
|
420 |
|
421 if (err != KErrNone) |
|
422 { |
|
423 TFileName name = aLibrary.FileName(); |
|
424 DEBUGPRINT3(_L("Error %d when calling first function in State Policy DLL %S."), err, &name); |
|
425 } |
|
426 User::LeaveIfError(err); |
|
427 CleanupStack::PushL(frame); |
|
428 return frame; |
|
429 } |
|
430 |
|
431 /** |
|
432 */ |
|
433 CSsmSwpPolicyFrame* CSsmSwpTransitionEngineTest::GetSwpPolicyL(const TSsmSwp& aSwp) |
|
434 { |
|
435 RLibrary library; |
|
436 const TInt fileErr = library.Load(KTestSwpPolicyGenericFile); |
|
437 if (fileErr != KErrNone) |
|
438 { |
|
439 RDebug::Print(_L("Failed to load library file %S, file error-code: %d"), &KTestSwpPolicyGenericFile(), fileErr); |
|
440 User::Leave(fileErr); |
|
441 } |
|
442 |
|
443 // make a process-owned copy of the handle as it has to be used by SsmSwpPolicyServer, |
|
444 // which runs in a separate thread |
|
445 User::LeaveIfError(library.Duplicate(RThread(), EOwnerProcess)); |
|
446 |
|
447 CSsmSwpPolicyFrame* policy = CreatePolicyLC(library); |
|
448 CleanupStack::Pop(policy); |
|
449 policy->SetLibrary(library); // takes ownership of open library handle |
|
450 policy->SetSwpKey(aSwp.Key()); |
|
451 |
|
452 RDebug::Print(_L("Created Swp Policy DLL %S"), &KTestSwpPolicyGenericFile()); |
|
453 |
|
454 return policy; |
|
455 } |
|
456 |
|
457 |
|
458 |
|
459 |