sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // @file testcaseroot.cpp sl@0: // @internalComponent sl@0: // sl@0: // sl@0: sl@0: #include <e32std.h> sl@0: #include <e32std_private.h> sl@0: #include <u32std.h> // unicode builds sl@0: #include <e32base.h> sl@0: #include <e32base_private.h> sl@0: #include <e32cons.h> sl@0: #include <e32Test.h> // RTest header sl@0: //#include <e32ver.h> sl@0: #include <e32def.h> sl@0: #include <e32def_private.h> sl@0: #include <d32otgdi.h> // OTGDI header sl@0: #include <d32usbc.h> // USBCC header sl@0: #include "testcaseroot.h" sl@0: sl@0: /* Implemention of classes CTestCaseRoot, CTestCaseB2BRoot sl@0: * sl@0: */ sl@0: sl@0: /* =============================================================== sl@0: * The root test-case class, provides test-framework features sl@0: */ sl@0: CTestCaseRoot::CTestCaseRoot(const TDesC& aTestCaseId, TBool aAutomation) sl@0: : CActive(EPriorityUserInput), sl@0: COtgRoot(), sl@0: iAutomated(aAutomation) sl@0: { sl@0: iTestCaseId.Copy(aTestCaseId); sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::BaseConstructL() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: sl@0: TInt err(iTimer.CreateLocal()); sl@0: if (err == KErrNone) sl@0: { sl@0: LOG_VERBOSE1(_L("Test case timer created")); sl@0: } sl@0: else sl@0: { sl@0: RDebug::Printf("<Error %d> Test case timer could not be created",err); sl@0: User::Leave(err); sl@0: } sl@0: // sl@0: iConsole = test.Console(); sl@0: iRequestedChar = EFalse; sl@0: } sl@0: sl@0: sl@0: CTestCaseRoot::~CTestCaseRoot() sl@0: { sl@0: LOG_FUNC sl@0: Cancel(); sl@0: } sl@0: sl@0: // utility GUI methods sl@0: void CTestCaseRoot::DisplayTestCaseOptions() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: // commonly overridden to display any options for that test sl@0: test.Printf(_L("Press <ESC> to end the test.\n")); sl@0: } sl@0: sl@0: sl@0: /***********************************************************************/ sl@0: // sl@0: void CTestCaseRoot::SetTestPolicy(CBasicTestPolicy* aTestPolicy) sl@0: { sl@0: iTestPolicy = aTestPolicy; sl@0: iAutomated = gSemiAutomated; // read the global flag at this time sl@0: } sl@0: sl@0: sl@0: CBasicTestPolicy& CTestCaseRoot::TestPolicy() sl@0: { sl@0: return *iTestPolicy; sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::DoCancel() sl@0: { sl@0: LOG_FUNC sl@0: } sl@0: sl@0: sl@0: /** ProcessKey sl@0: override this method to perform other tasks, the base-class does nothing so that sl@0: child classes can use it as an any-key-to-continue helper sl@0: */ sl@0: void CTestCaseRoot::ProcessKey(TKeyCode &aKey) sl@0: {// default implementation - reads the key. sl@0: iKeyCodeInput = aKey; sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::ProcessEngineKey(TKeyCode &aKey) sl@0: { sl@0: LOG_FUNC sl@0: sl@0: if (EKeyEscape == aKey) sl@0: { sl@0: AssertionFailed( 1, _L("Test aborted by the user <ESC>\n")); sl@0: CActiveScheduler::Stop(); sl@0: } sl@0: else sl@0: { sl@0: sl@0: // call virtual method here to invoke the test's overridden method sl@0: ProcessKey(aKey); sl@0: // note, we do not go ask for another, that is done by the console handler sl@0: } sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::RequestCharacter() sl@0: { sl@0: LOG_FUNC sl@0: // A request is issued to the CConsoleBase to accept a sl@0: // character from the keyboard. sl@0: sl@0: __ASSERT_ALWAYS(!IsActive(), User::Panic(KMsgAlreadyActive, EPanicAlreadyActive)); sl@0: sl@0: iConsole->Read(iStatus); sl@0: SetActive(); sl@0: iRequestedChar = ETrue; sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::RunL() sl@0: { sl@0: LOG_FUNC sl@0: TInt complCode(iStatus.Int()); sl@0: if (iRequestedChar) sl@0: { sl@0: sl@0: TKeyCode k(iConsole->KeyCode()); sl@0: sl@0: // WARNING! sl@0: // EMULATOR QUIRK! sl@0: // When debugging if you have a breakpoint just before you read/process a key, sl@0: // the EMULATOR will read the key sent to the IDE and you get a (F5) key that sl@0: // you did not want from the IDE not the emulator. sl@0: sl@0: ProcessEngineKey(k); sl@0: iRequestedChar = EFalse; sl@0: sl@0: // complete so that other tasks (there are none) can run sl@0: // we will then be scheduled by the ActiveScheduler again to run the next test step. sl@0: SelfComplete(); sl@0: } sl@0: else sl@0: { sl@0: // run the next test step sl@0: TInt currentStep(GetStepIndex()); sl@0: PreRunStep(); sl@0: LOG_VERBOSE2(_L("\n<< RunStepL() step=%d\n"), currentStep); sl@0: RunStepL(); sl@0: LOG_VERBOSE3(_L(">> RunStepL() step=%d->%d\n"), currentStep, GetStepIndex()); sl@0: PostRunStep(); sl@0: } sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::PostRunStep() sl@0: { sl@0: // default impl. sl@0: } sl@0: sl@0: void CTestCaseRoot::PreRunStep() sl@0: { sl@0: // default impl. sl@0: } sl@0: sl@0: TInt CTestCaseRoot::RunError(TInt aError) sl@0: { sl@0: LOG_FUNC sl@0: test.Printf(_L("Test case C%lS::RunL left with %d"), &iTestCaseId, aError); sl@0: AssertionFailed(aError, _L("RunError")); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TDesC& CTestCaseRoot::TestCaseId() sl@0: { sl@0: return iTestCaseId; sl@0: } sl@0: sl@0: sl@0: TInt CTestCaseRoot::TestResult() const sl@0: { sl@0: return iTestResult; sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::PerformTestL() sl@0: { sl@0: // tell user what they should have done before starting! sl@0: DescribePreconditions(); sl@0: // run it sl@0: ExecuteTestCaseL(); sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::TestFailed(TInt aFailResult, const TDesC &aErrorDescription) sl@0: { sl@0: LOG_FUNC sl@0: iTestResult = aFailResult; sl@0: test.Printf(_L("Test %S\n"), &TestCaseId()); sl@0: test.Printf(_L("Failed (%d)\n"), aFailResult); sl@0: test.Printf(_L("%S!\n"), &aErrorDescription); sl@0: if (!iAutomated) sl@0: { sl@0: test.Printf(_L("\n")); sl@0: test.Printf(KPressAnyKeyToContinue); sl@0: iConsole->Getch(); sl@0: } sl@0: // the next call panics the framework! sl@0: TestPolicy().SignalTestComplete(iTestResult); sl@0: } sl@0: sl@0: sl@0: void CTestCaseRoot::TestFailed2(TInt aFailResult, const TDesC &aErrorDescription, TInt errorCode) sl@0: { sl@0: LOG_FUNC sl@0: iTestResult = aFailResult; sl@0: test.Printf(_L("Test %S FAILED %d '%S %d'!\n"), sl@0: &TestCaseId(), sl@0: aFailResult, sl@0: &aErrorDescription, sl@0: errorCode); sl@0: // the next call panics the framework! sl@0: TestPolicy().SignalTestComplete(iTestResult); sl@0: } sl@0: sl@0: sl@0: sl@0: void CTestCaseRoot::TestPassed() sl@0: { sl@0: LOG_FUNC sl@0: iTestResult = KErrNone; sl@0: TestPolicy().SignalTestComplete(iTestResult); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** Complete the servicing of the Active object and signal it ready to run again sl@0: in next scheduler slot. This method works as drop-through when a test step has sl@0: nothing more to do . sl@0: */ sl@0: void CTestCaseRoot::SelfComplete(TInt aCode) sl@0: { sl@0: TRequestStatus* s = &iStatus; sl@0: iStatus = KRequestPending; sl@0: User::RequestComplete(s, aCode); sl@0: SetActive(); sl@0: } sl@0: sl@0: /* Prints a little banner at the top of a test-step : sl@0: * B2B tests also display the duration of the last step, and the current OTG state sl@0: */ sl@0: void CTestCaseRoot::PrintStepName(const TDesC &aStepName) sl@0: { sl@0: if (gVerboseOutput) sl@0: { sl@0: test.Printf(_L("--------------\n %S "), &aStepName); sl@0: // B2B class method dumps the engine state sl@0: // sl@0: test.Printf(_L("\n--------------\n")); sl@0: } sl@0: } sl@0: sl@0: sl@0: /* ************************************************************************************** sl@0: * sl@0: */ sl@0: CTestCaseB2BRoot::CTestCaseB2BRoot(const TDesC& aTestCaseId, TBool aHost, TRequestStatus &aStatus) sl@0: : CTestCaseRoot(aTestCaseId, aHost) , iCollector(aStatus) sl@0: { sl@0: LOG_FUNC sl@0: sl@0: } sl@0: sl@0: sl@0: CTestCaseB2BRoot::~CTestCaseB2BRoot() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: } sl@0: sl@0: /* Print step name : B2B override displays the OTG Engine state as well sl@0: */ sl@0: void CTestCaseB2BRoot::PrintStepName(const TDesC &aStepName) sl@0: { sl@0: if (gVerboseOutput) sl@0: { sl@0: test.Printf(_L("--------------\n %S "), &aStepName); sl@0: // engine state sl@0: CNotifyWatcherBase *pWatcher = iCollector.GetWatcher(EWatcherState); sl@0: if (pWatcher) sl@0: { sl@0: TBuf<MAX_DSTRLEN> aDescription; sl@0: RUsbOtgDriver::TOtgState aState = static_cast<RUsbOtgDriver::TOtgState>(pWatcher->GetEventValue()); sl@0: sl@0: OtgStateString(aState, aDescription); sl@0: LOG_VERBOSE3(_L("OTGState %d '%S' \n"), aState, &aDescription); sl@0: } sl@0: test.Printf(_L(" : time = %dms\n--------------\n"), iCollector.DurationElapsed()); sl@0: } sl@0: } sl@0: sl@0: /* Default implementation which describes this as a B2B test-case sl@0: */ sl@0: void CTestCaseB2BRoot::DescribePreconditions() sl@0: { sl@0: test.Printf(KTestTypeB2BMsg); // B2B sl@0: if (gTestRoleMaster) sl@0: test.Printf(KRoleMasterMsg); sl@0: else sl@0: test.Printf(KRoleSlaveMsg); sl@0: } sl@0: sl@0: sl@0: void CTestCaseB2BRoot::StepB2BPreconditions() sl@0: { sl@0: // prompt to insert connector sl@0: if (gTestRoleMaster) sl@0: { // "B" device sl@0: test.Printf(KInsertBCablePrompt); sl@0: } sl@0: else sl@0: { sl@0: test.Printf(KInsertACablePrompt); sl@0: } sl@0: if (iAutomated) sl@0: { sl@0: sl@0: SelfComplete(); sl@0: return; sl@0: } sl@0: test.Printf(KPressAnyKeyToContinue); sl@0: RequestCharacter(); sl@0: } sl@0: sl@0: sl@0: /* Test for A or B plug as relevant for MASTER/SLAVE role, fail the test if wrong sl@0: */ sl@0: void CTestCaseB2BRoot::CheckRoleConnections() sl@0: { sl@0: if (gTestRoleMaster) sl@0: { sl@0: if (otgIdPinPresent()) sl@0: { // oops sl@0: test.Printf(KMsgErrorPreconditionFailed); sl@0: return TestFailed(KErrAbort, KMsgBPlugNotFound); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (!otgIdPinPresent()) sl@0: { // oops sl@0: test.Printf(KMsgErrorPreconditionFailed); sl@0: return TestFailed(KErrAbort, KMsgAPlugNotFound); sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: /* Clears the expected event Q just before calling the step, but not the sl@0: * recieved Q since the step may still inspect it using the EventReceivedAlready() method. sl@0: */ sl@0: void CTestCaseB2BRoot::PreRunStep() sl@0: { sl@0: LOG_FUNC sl@0: sl@0: iCollector.ClearAllEvents(EFalse, ETrue); sl@0: } sl@0: sl@0: sl@0: void CTestCaseB2BRoot::PostRunStep() sl@0: { sl@0: LOG_FUNC sl@0: // clear the recieved event Q, but not the expected Q sl@0: iCollector.ClearAllEvents(ETrue, EFalse); sl@0: sl@0: } sl@0: sl@0: sl@0: