diff -r 000000000000 -r 4e1aa6a622a0 sysstatemgmt/systemstatemgr/test/tssm/src/tssm_step_swptransitionengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sysstatemgmt/systemstatemgr/test/tssm/src/tssm_step_swptransitionengine.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,459 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +/** + @file + @test + @internalComponent - Internal Symbian test code +*/ + + +#include + +#include "ssmswppolicyframe.h" +#include "ssmswptransitionengine.h" + +#include "ssmatest_utils.h" +#include "tssm_step_swptransitionengine.h" +#include "tssm_swppolicy_generic.h" +#include "tssm_swppolicy_generic.hrh" + +#include + +// Keys and values used for testing the transition engines +static const TUint KSwpTestKey1 = 0xE5325221; + +const TInt KTestErrorBadCategory = -911; +const TInt KTestErrorBadFunction = -912; + +/** +*/ +static TInt StopScheduler(TAny* aSsmSwpTransitionEngineTest) + { + CSsmSwpTransitionEngineTest* ssmSwpRequestEngineTest = static_cast(aSsmSwpTransitionEngineTest); + ssmSwpRequestEngineTest->StopActiveScheduler(); + return KErrNone; + } + +//--------------------- Thread creation framework --------------------- + +/** +Test framework to check for panic scenarios +It requires to create a separate thread so we can check the panic category and code. +*/ +TInt StartTestInThreadL(TInt aFunction) + { + RThread thread; + // Give each thread a unique name to avoid KErrAlreadyExists error on thread creation + _LIT(KThreadNamePrefix, "SsmTestThread"); + RBuf threadName; + CleanupClosePushL(threadName); + threadName.CreateL(KThreadNamePrefix().Length() + 4); // 4 digit thread number + threadName = KThreadNamePrefix; + threadName.AppendNumFixedWidth(aFunction, EDecimal, 4); + const TInt KMinHeapSize = 0xc800; // 50k - NOTE just an arbitrary value, please feel free to change it + const TInt KMaxHeapSize = 0x19000; // 100k - NOTE just an arbitrary value, please feel free to change it + User::LeaveIfError(thread.Create(threadName, ThreadStartFn, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, (TAny*)aFunction)); + CleanupStack::PopAndDestroy(&threadName); + TRequestStatus status; + thread.Logon(status); + TBool jit = User::JustInTime(); + User::SetJustInTime(EFalse); + thread.Resume(); + User::WaitForRequest(status); + + // always expecting a transition engine panic + TExitCategoryName category = thread.ExitCategory(); + RDebug::Print(_L("***** Exit Category = %S *****"),&category); + if (category.Compare(KPanicSysStateMgr) != 0) + { + User::Leave(KTestErrorBadCategory); + } + const TInt exitReason = thread.ExitReason(); + thread.Close(); + User::SetJustInTime(jit); + + // return the exit reason for the caller to verify the expected panic value + return exitReason; + } + +TInt ThreadStartFn(TAny* aPtr) + { + CTrapCleanup* trapCleanup = CTrapCleanup::New(); + if (!trapCleanup) + { + return KErrNoMemory; + } + + TInt function = (TInt)aPtr; + TRAPD(err, ThreadDispatchFunctionL(function)); + + delete trapCleanup; + return err; + } + + +void ThreadDispatchFunctionL(TInt aFunction) + { + switch (aFunction) + { + case EThreadSubmitTwice: + ThreadSubmitTwiceL(); + break; + default: + User::Leave(KTestErrorBadFunction); + break; + } + } + + +void ThreadSubmitTwiceL() + { + CSsmSwpTransitionEngineTest* step = new (ELeave) CSsmSwpTransitionEngineTest(); + + CActiveScheduler* activeScheduler = new(ELeave) CActiveScheduler; + CleanupStack::PushL(activeScheduler); + CActiveScheduler::Install(activeScheduler); + + CAsyncCallBack* asyncStopScheduler = new(ELeave) CAsyncCallBack(CActive::EPriorityIdle); + TCallBack stop(StopScheduler, step); + asyncStopScheduler->Set(stop); + CleanupStack::Pop(activeScheduler); + + // ssmswppolicyproxy is created and set by the individualtransitionscheduler, since + // we are submitting the request directly to the engine the ssmswppolicyproxy should be + // created and set in the engine + CSsmSwpPolicyCliSession* ssmSwpPolicySession = CSsmSwpPolicyCliSession::NewL(); + CleanupStack::PushL(ssmSwpPolicySession); + + // Setting the cle session as we have to execute the publishswp command. + // published swp value is used to stop the scheduler. + CCleSessionProxy* cleSession = CCleSessionProxy::NewL(); + CleanupStack::PushL(cleSession); + + const TSsmSwp swpValue(KSwpTestKey1, ESwpGenericDoNothing); + CSsmSwpPolicyFrame* policy = step->GetSwpPolicyL(swpValue); + CleanupStack::PushL(policy); + + CSsmSwpTransitionEngine* engine = CSsmSwpTransitionEngine::NewL(swpValue); + engine->SetCleSessionProxy(cleSession); + engine->SetSwpPolicyFrame(policy); + engine->SetSsmSwpPolicySession(ssmSwpPolicySession); + CleanupStack::Pop(policy); + + CleanupStack::PushL(engine); + engine->Submit(); + engine->Submit(); + // etc, etc, etc.. + // don't bother to continue here. All being well the second SubmitL will cause a panic! + //Cleanup test + CleanupStack::PopAndDestroy(3, ssmSwpPolicySession); // and engine + } + + +//----------------- CTestStep implemenation -------------------- + +/** +*/ +CSsmSwpTransitionEngineTest::~CSsmSwpTransitionEngineTest() + { + iProperty.Close(); + delete iAsyncStopScheduler; + delete iActiveScheduler; + } + +/** +*/ +CSsmSwpTransitionEngineTest::CSsmSwpTransitionEngineTest() + { + SetTestStepName(KTSsmSwpTransitionEngineStep); + } + +/** +*/ +TVerdict CSsmSwpTransitionEngineTest::doTestStepPreambleL() + { + iActiveScheduler = new(ELeave) CActiveScheduler; + CActiveScheduler::Install (iActiveScheduler); + + iAsyncStopScheduler = new(ELeave) CAsyncCallBack(CActive::EPriorityIdle); + TCallBack stop(StopScheduler, this); + iAsyncStopScheduler->Set(stop); + + return CTestStep::doTestStepPreambleL(); + } + +/** +Old Test CaseID APPFWK-SSM-0007 +New Test CaseID DEVSRVS-SSMA-SSM-0007 + */ + +TVerdict CSsmSwpTransitionEngineTest::doTestStepL() + { + INFO_PRINTF1(_L("CSsmSwpTransitionEngineTest started....")); + + __UHEAP_MARK; + + doTestSwpTransitionEngineTestForMemoryLeaksL(); + doTestRequestSimpleL(); + doTestRequestCancelL(); + doTestRequestSubmitTwiceL(); + + __UHEAP_MARKEND; + + INFO_PRINTF1(_L("....CSsmSwpTransitionEngineTest completed!!")); + return TestStepResult(); + } + +/** +*/ +TVerdict CSsmSwpTransitionEngineTest::doTestStepPostambleL() + { + return CTestStep::doTestStepPostambleL(); + } + +/** +*/ +void CSsmSwpTransitionEngineTest::doTestSwpTransitionEngineTestForMemoryLeaksL() + { + INFO_PRINTF1(_L("Checking for destructor memoryleaks in CSsmSwpTransitionEngine")); + + __UHEAP_MARK; + + // ssmswppolicyproxy is created and set by the individualtransitionscheduler, since + // we are submitting the request directly to the engine the ssmswppolicyproxy should be + // created and set in the engine + CSsmSwpPolicyCliSession* ssmSwpPolicySession = CSsmSwpPolicyCliSession::NewL(); + CleanupStack::PushL(ssmSwpPolicySession); + + // Setting the cle session as we have to execute the publishswp command. + // published swp value is used to stop the scheduler. + CCleSessionProxy* cleSession = CCleSessionProxy::NewL(); + CleanupStack::PushL(cleSession); + + const TSsmSwp swpValue(KSwpTestKey1, ESwpGenericDoNothing); + CSsmSwpPolicyFrame* policy = this->GetSwpPolicyL(swpValue); + CleanupStack::PushL(policy); + + CSsmSwpTransitionEngine* engine = CSsmSwpTransitionEngine::NewL(swpValue); + engine->SetCleSessionProxy(cleSession); + engine->SetSwpPolicyFrame(policy); + engine->SetSsmSwpPolicySession(ssmSwpPolicySession); + CleanupStack::Pop(policy); + + //Cleanup test + CleanupStack::PopAndDestroy(2, ssmSwpPolicySession); + delete engine; + + __UHEAP_MARKEND; + } + +/** +Takes CSsmSwpTransitionEngine through the simple swp transition. +*/ +void CSsmSwpTransitionEngineTest::doTestRequestSimpleL() + { + INFO_PRINTF1(_L("Checking requesthandler with a single request")); + + __UHEAP_MARK; + + // ssmswppolicyproxy is created and set by the individualtransitionscheduler, but + // we are submitting the request directly to the engine the ssmswppolicyproxy should be + // created and set in the engine + CSsmSwpPolicyCliSession* ssmSwpPolicySession = CSsmSwpPolicyCliSession::NewL(); + CleanupStack::PushL(ssmSwpPolicySession); + + // Setting the cle session as we have to execute the publishswp command. + // published swp value is used to stop the scheduler. + CCleSessionProxy* cleSession = CCleSessionProxy::NewL(); + CleanupStack::PushL(cleSession); + + // Define and set the rproperty + TEST(KErrNone == iProperty.Define(RProcess().SecureId(), KSwpTestKey1, RProperty::EInt)); + TEST(KErrNone == iProperty.Set(RProcess().SecureId(), KSwpTestKey1, 0)); + + TInt value; + TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); + TEST(value == 0); + + const TSsmSwp swpValue(KSwpTestKey1, ESwpGenericDoNothing); + CSsmSwpPolicyFrame* policy = this->GetSwpPolicyL(swpValue); + CleanupStack::PushL(policy); + + CSsmSwpTransitionEngine* engine = CSsmSwpTransitionEngine::NewL(swpValue); + engine->SetCleSessionProxy(cleSession); + engine->SetSwpPolicyFrame(policy); + engine->SetSsmSwpPolicySession(ssmSwpPolicySession); + engine->PerformCommandListValidation(EFalse); + CleanupStack::Pop(policy); + + CleanupStack::PushL(engine); + engine->Submit(); + + //this callback will not run until the test is finished because it has priority idle + iAsyncStopScheduler->CallBack(); + //run engine + iActiveScheduler->Start(); + + TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); + TEST(value == ESwpGenericDoNothing); + + TEST(KErrNone == iProperty.Delete(RProcess().SecureId(), KSwpTestKey1)); + + //Cleanup test + CleanupStack::PopAndDestroy(3, ssmSwpPolicySession); // and engine + + __UHEAP_MARKEND; + } + +/** +Takes CSsmSwpTransitionEngine through the simple swp transition and cancels it. +*/ +void CSsmSwpTransitionEngineTest::doTestRequestCancelL() + { + INFO_PRINTF1(_L("Checking requesthandler with a cancel request")); + + __UHEAP_MARK; + + // ssmswppolicyproxy is created and set by the individualtransitionscheduler, but + // we are submitting the request directly to the engine the ssmswppolicyproxy should be + // created and set in the engine + CSsmSwpPolicyCliSession* ssmSwpPolicySession = CSsmSwpPolicyCliSession::NewL(); + CleanupStack::PushL(ssmSwpPolicySession); + + // Setting the cle session as we have to execute the publishswp command. + // published swp value is used to stop the scheduler. + CCleSessionProxy* cleSession = CCleSessionProxy::NewL(); + CleanupStack::PushL(cleSession); + + // Define and set the rproperty + TEST(KErrNone == iProperty.Define(RProcess().SecureId(), KSwpTestKey1, RProperty::EInt)); + TEST(KErrNone == iProperty.Set(RProcess().SecureId(), KSwpTestKey1, -5)); + + TInt value; + TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); + TEST(value == -5); + + const TSsmSwp swpValue(KSwpTestKey1, ESwpGenericDoNothing); + CSsmSwpPolicyFrame* policy = this->GetSwpPolicyL(swpValue); + CleanupStack::PushL(policy); + + CSsmSwpTransitionEngine* engine = CSsmSwpTransitionEngine::NewL(swpValue); + engine->SetCleSessionProxy(cleSession); + engine->SetSwpPolicyFrame(policy); + engine->SetSsmSwpPolicySession(ssmSwpPolicySession); + engine->PerformCommandListValidation(EFalse); + CleanupStack::Pop(policy); + + CleanupStack::PushL(engine); + engine->Submit(); + engine->Cancel(); + + //this callback will not run until the test is finished because it has priority idle + iAsyncStopScheduler->CallBack(); + //run engine + iActiveScheduler->Start(); + + TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); + TEST(value == -5); + + TEST(KErrNone == iProperty.Delete(RProcess().SecureId(), KSwpTestKey1)); + + //Cleanup test + CleanupStack::PopAndDestroy(3, ssmSwpPolicySession); // and engine + + __UHEAP_MARKEND; + } + +void CSsmSwpTransitionEngineTest::doTestRequestSubmitTwiceL() + { + INFO_PRINTF1(_L("Checking requesthandler with two consecutive requests")); + TInt exitReason(0); + TRAPD(err, exitReason = StartTestInThreadL(EThreadSubmitTwice)); + TEST(err == KErrNone); + INFO_PRINTF2(_L(" 3-- StartTestInThreadL method completed with '%d'."), err); + TEST(exitReason == ESwpTransitionEngineError3); + INFO_PRINTF3(_L(" 3-- received panic '%d', expected was '%d'."), exitReason, ESwpTransitionEngineError3); + + // this test raises panics due to negative testing - close them to clear the screen. + CloseAllPanicWindowsL(); + } + +void CSsmSwpTransitionEngineTest::StopActiveScheduler() + { + // We would stop the sceduler once all the required transitions are completed + //Verify that the expected calls were made + TInt value; + TEST(KErrNone == iProperty.Get(RProcess().SecureId(), KSwpTestKey1, value)); + + // We have to stop the scheduler in case of Cancel test code, so testing property's initial value. + if (value == ESwpGenericDoNothing || value == -5) + { + CActiveScheduler::Stop(); + } + else + { + iAsyncStopScheduler->CallBack(); + } + } + +//----------------- MPolicyResolverProxy implementation -------------------- + +CSsmSwpPolicyFrame* CSsmSwpTransitionEngineTest::CreatePolicyLC(const RLibrary& aLibrary) const + { + __ASSERT_DEBUG( KNullHandle != aLibrary.Handle(), PanicNow(KPanicSysStateMgr, ESwpPolicyResolverLibraryNotLoaded)); + + CSsmSwpPolicyFrame* frame = NULL; + TRAPD(err, frame = CSsmSwpPolicyFrame::NewL(aLibrary.Lookup(1))); + + if (err != KErrNone) + { + TFileName name = aLibrary.FileName(); + DEBUGPRINT3(_L("Error %d when calling first function in State Policy DLL %S."), err, &name); + } + User::LeaveIfError(err); + CleanupStack::PushL(frame); + return frame; + } + +/** +*/ +CSsmSwpPolicyFrame* CSsmSwpTransitionEngineTest::GetSwpPolicyL(const TSsmSwp& aSwp) + { + RLibrary library; + const TInt fileErr = library.Load(KTestSwpPolicyGenericFile); + if (fileErr != KErrNone) + { + RDebug::Print(_L("Failed to load library file %S, file error-code: %d"), &KTestSwpPolicyGenericFile(), fileErr); + User::Leave(fileErr); + } + + // make a process-owned copy of the handle as it has to be used by SsmSwpPolicyServer, + // which runs in a separate thread + User::LeaveIfError(library.Duplicate(RThread(), EOwnerProcess)); + + CSsmSwpPolicyFrame* policy = CreatePolicyLC(library); + CleanupStack::Pop(policy); + policy->SetLibrary(library); // takes ownership of open library handle + policy->SetSwpKey(aSwp.Key()); + + RDebug::Print(_L("Created Swp Policy DLL %S"), &KTestSwpPolicyGenericFile()); + + return policy; + } + + + +