kerneltest/e32test/usbho/t_otgdi/src/testcaseroot.cpp
author Slion
Tue, 08 Dec 2009 08:11:42 +0100
branchanywhere
changeset 19 f6d3d9676ee4
parent 0 a41df078684a
child 253 d37db4dcc88d
permissions -rw-r--r--
Trying to figure out how to implement my WINC like compatibility layer. Going the emulation way is probably not so smart. We should not use the kernel but rather hook native functions in the Exec calls.

// 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 the License "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 testcaseroot.cpp
// @internalComponent
// 
//

#include <e32std.h>
#include <e32std_private.h>
#include <u32std.h> 	// unicode builds
#include <e32base.h>
#include <e32base_private.h>
#include <e32cons.h>
#include <e32Test.h>	// RTest header
//#include <e32ver.h>
#include <e32def.h>
#include <e32def_private.h>
#include <d32otgdi.h>		// OTGDI header
#include <d32usbc.h>		// USBCC header
#include "testcaseroot.h"

/* Implemention of classes CTestCaseRoot, CTestCaseB2BRoot
 *
 */ 

/* ===============================================================
 *  The root test-case class, provides test-framework features  
 */
CTestCaseRoot::CTestCaseRoot(const TDesC& aTestCaseId, TBool aAutomation)
:	CActive(EPriorityUserInput),
	COtgRoot(),
	iAutomated(aAutomation)
	{
	iTestCaseId.Copy(aTestCaseId);
	}

	
void CTestCaseRoot::BaseConstructL()
	{
	LOG_FUNC
	

	TInt err(iTimer.CreateLocal());
	if (err == KErrNone)
		{
		LOG_VERBOSE1(_L("Test case timer created"));
		}
	else
		{
		RDebug::Printf("<Error %d> Test case timer could not be created",err);
		User::Leave(err);
		}
	//
	iConsole = test.Console();
	iRequestedChar = EFalse;
	}
	
	
CTestCaseRoot::~CTestCaseRoot()
	{
	LOG_FUNC
	Cancel();
	}

// utility GUI methods
void CTestCaseRoot::DisplayTestCaseOptions()
	{
	LOG_FUNC

	// commonly overridden to display any options for that test
	test.Printf(_L("Press <ESC> to end the test.\n"));	
	}

    
/***********************************************************************/
//
void CTestCaseRoot::SetTestPolicy(CBasicTestPolicy* aTestPolicy)
	{
	iTestPolicy = aTestPolicy;
	iAutomated = gSemiAutomated;	// read the global flag at this time
	}


CBasicTestPolicy& CTestCaseRoot::TestPolicy()
	{
	return *iTestPolicy;
	}
	

void CTestCaseRoot::DoCancel()
	{
	LOG_FUNC
	}

    
/** ProcessKey
override this method to perform other tasks, the base-class does nothing so that 
child classes can use it as an any-key-to-continue helper
*/
void CTestCaseRoot::ProcessKey(TKeyCode &aKey)
	{// default implementation - reads the key.
		iKeyCodeInput = aKey;
	}
    
    
void CTestCaseRoot::ProcessEngineKey(TKeyCode &aKey)
	{
	LOG_FUNC
	
	if (EKeyEscape == aKey)
		{
		AssertionFailed( 1, _L("Test aborted by the user <ESC>\n"));
		CActiveScheduler::Stop();
		}
	else
		{
			
		// call virtual method here to invoke the test's overridden method
		ProcessKey(aKey);
		// note, we do not go ask for another, that is done by the console handler
		}
	}
    

void CTestCaseRoot::RequestCharacter()
	{
	LOG_FUNC
	  // A request is issued to the CConsoleBase to accept a
	  // character from the keyboard.

	__ASSERT_ALWAYS(!IsActive(), User::Panic(KMsgAlreadyActive, EPanicAlreadyActive));
	  
	iConsole->Read(iStatus); 
	SetActive();
	iRequestedChar = ETrue;
	}


void CTestCaseRoot::RunL()
	{
	LOG_FUNC
	TInt complCode(iStatus.Int());
	if (iRequestedChar)
		{
		
		TKeyCode k(iConsole->KeyCode());
		
		// WARNING!
		// EMULATOR QUIRK!
		// When debugging if you have a breakpoint just before you read/process a key, 
		// the EMULATOR will read the key sent to the IDE and you get a (F5) key that 
		// you did not want from the IDE not the emulator.
		
		ProcessEngineKey(k);
		iRequestedChar = EFalse;

		// complete so that other tasks (there are none) can run
		// we will then be scheduled by the ActiveScheduler again to run the next test step.
		SelfComplete();
		}
	else
		{
		// run the next test step
		TInt currentStep(GetStepIndex());
		PreRunStep();
		LOG_VERBOSE2(_L("\n<< RunStepL() step=%d\n"), currentStep);
		RunStepL();
		LOG_VERBOSE3(_L(">> RunStepL() step=%d->%d\n"), currentStep, GetStepIndex());
		PostRunStep();
		}
	}


void CTestCaseRoot::PostRunStep()
	{
		// default impl.
	}

void CTestCaseRoot::PreRunStep()
	{
		// default impl.
	}

TInt CTestCaseRoot::RunError(TInt aError)
	{
	LOG_FUNC
	test.Printf(_L("Test case C%lS::RunL left with %d"), &iTestCaseId, aError);
	AssertionFailed(aError, _L("RunError"));
	return KErrNone;
	}
	
	
TDesC& CTestCaseRoot::TestCaseId()
	{
	return iTestCaseId;
	}
	
	
TInt CTestCaseRoot::TestResult() const
	{
	return iTestResult;
	}
	
	
void CTestCaseRoot::PerformTestL()
	{
		// tell user what they should have done before starting!
		DescribePreconditions();
		// run it
		ExecuteTestCaseL();
	}


void CTestCaseRoot::TestFailed(TInt aFailResult, const TDesC &aErrorDescription)
	{
	LOG_FUNC
	iTestResult = aFailResult;
	test.Printf(_L("Test %S\n"), &TestCaseId());
	test.Printf(_L("Failed (%d)\n"), aFailResult);
	test.Printf(_L("%S!\n"), &aErrorDescription);
	if (!iAutomated)
		{
		test.Printf(_L("\n"));
		test.Printf(KPressAnyKeyToContinue);
		iConsole->Getch();
		}
	// the next call panics the framework!
	TestPolicy().SignalTestComplete(iTestResult);
	}
	
	
void CTestCaseRoot::TestFailed2(TInt aFailResult, const TDesC &aErrorDescription, TInt errorCode)
	{
	LOG_FUNC
	iTestResult = aFailResult;
	test.Printf(_L("Test %S FAILED %d '%S %d'!\n"), 
	            &TestCaseId(), 
	            aFailResult, 
	            &aErrorDescription, 
	            errorCode);
	// the next call panics the framework!
	TestPolicy().SignalTestComplete(iTestResult);
	}
	
	
	
void CTestCaseRoot::TestPassed()
	{
	LOG_FUNC
	iTestResult = KErrNone;
	TestPolicy().SignalTestComplete(iTestResult);
	}
	
	
	
			
/** Complete the servicing of the Active object and signal it ready to run again 
 in next scheduler slot. This method works as drop-through when a test step has 
 nothing more to do .
*/
void CTestCaseRoot::SelfComplete(TInt aCode)
	{	
	TRequestStatus* s = &iStatus;
	iStatus = KRequestPending;
	User::RequestComplete(s, aCode);
	SetActive();
	}

/* Prints a little banner at the top of a test-step : 
 * B2B tests also display the duration of the last step, and the current OTG state
 */
void CTestCaseRoot::PrintStepName(const TDesC &aStepName)
	{
	if (gVerboseOutput) 
		{
		test.Printf(_L("--------------\n %S "), &aStepName);
		// B2B class method dumps the engine state
		//
		test.Printf(_L("\n--------------\n"));
		}
	}


/* **************************************************************************************
 * 
 */
CTestCaseB2BRoot::CTestCaseB2BRoot(const TDesC& aTestCaseId, TBool aHost, TRequestStatus &aStatus) 
	: CTestCaseRoot(aTestCaseId, aHost) , iCollector(aStatus)
	{
	LOG_FUNC
	
	}


CTestCaseB2BRoot::~CTestCaseB2BRoot()
	{
	LOG_FUNC
	
	}

/* Print step name : B2B override displays the OTG Engine state as well
 */
void CTestCaseB2BRoot::PrintStepName(const TDesC &aStepName)
	{
	if (gVerboseOutput) 
		{
		test.Printf(_L("--------------\n %S "), &aStepName);
		// engine state
		CNotifyWatcherBase *pWatcher = iCollector.GetWatcher(EWatcherState);
		if (pWatcher)
			{
			TBuf<MAX_DSTRLEN> aDescription;
			RUsbOtgDriver::TOtgState aState = static_cast<RUsbOtgDriver::TOtgState>(pWatcher->GetEventValue());
			
			OtgStateString(aState, aDescription);
			LOG_VERBOSE3(_L("OTGState %d '%S' \n"), aState, &aDescription);
			}
		test.Printf(_L(" : time = %dms\n--------------\n"), iCollector.DurationElapsed());
		}
	}

/* Default implementation which describes this as a B2B test-case 
 */
void CTestCaseB2BRoot::DescribePreconditions()
	{
	test.Printf(KTestTypeB2BMsg); // B2B
	if (gTestRoleMaster)
		test.Printf(KRoleMasterMsg);
	else
		test.Printf(KRoleSlaveMsg);
	}


void CTestCaseB2BRoot::StepB2BPreconditions()
	{
	// prompt to insert connector
	if (gTestRoleMaster)
		{ // "B" device
		test.Printf(KInsertBCablePrompt);
		}
	else
		{
		test.Printf(KInsertACablePrompt);
		}
	if (iAutomated)
		{

		SelfComplete();
		return;
		}
	test.Printf(KPressAnyKeyToContinue);
	RequestCharacter();	
	}


/* Test for A or B plug as relevant for MASTER/SLAVE role, fail the test if wrong
 */
void CTestCaseB2BRoot::CheckRoleConnections()
	{
	if (gTestRoleMaster)
		{
		if (otgIdPinPresent())
			{ // oops
			test.Printf(KMsgErrorPreconditionFailed);
			return TestFailed(KErrAbort, KMsgBPlugNotFound);
			}
		}
	else
		{
		if (!otgIdPinPresent())
			{ // oops
			test.Printf(KMsgErrorPreconditionFailed);
			return TestFailed(KErrAbort, KMsgAPlugNotFound);
			}
		}
	}


/* Clears the expected event Q just before calling the step, but not the 
 * recieved Q since the step may still inspect it using the EventReceivedAlready() method.
 */
void CTestCaseB2BRoot::PreRunStep()
	{
	LOG_FUNC
		
		iCollector.ClearAllEvents(EFalse, ETrue);
	}


void CTestCaseB2BRoot::PostRunStep()
	{
	LOG_FUNC
		// clear the recieved event Q, but not the expected Q
		iCollector.ClearAllEvents(ETrue, EFalse);
	
	}