kerneltest/e32test/usbho/t_otgdi/src/testengine.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:
// @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 headder
#include <e32def.h>
#include <e32def_private.h>
#include "debugmacros.h"
#include "TestEngine.h"
#include "TestCaseController.h"
#include "TestCaseFactory.h"
#include "TestCaseRoot.h"

// Console application parameter options
_LIT(KArgAllTestCases,"/ALL");			// see default test-list below
_LIT(KArgGoTestCase, "/G:");
_LIT(KArgAutomatedTest, "/AUTO");		// removes "press any key to continue" prompts
_LIT(KArgVerboseOutput, "/VERBOSE");	// also turns on RDebug logging of all test output (to serial)
_LIT(KArgSetOpenIterations, "/LOOPO:");	// Open/Close test loop count
_LIT(KArgSetOOMIterations, "/LOOPM:");	// OOM test set #allocs
_LIT(KArgSetRoleMaster, "/MASTER");		// this is the default
_LIT(KArgSetRoleSlave, "/SLAVE");		// slave - Runs a dual-role test's Slave steps instead of Master 
_LIT(KArgOverrideVidPid, "/PID:");		// vendor, product ID XXXX 4 hex digits /PID:0670

_LIT(KidFormatter,"PBASE-USB_OTGDI-%04d");
_LIT(KidFormatterS,"PBASE-USB_OTGDI-%S");

// '/ALL' tests grouping
const TInt KAllDefaultTestIDs[6] = 
	{
	456, // (a) PBASE-USB_OTG-0456 open/close 'A'
	457, // (a) PBASE-USB_OTG-0457 open/close disconnected
	459, // (m) PBASE-USB_OTG-0459 detect 'A'
	460, // (m) PBASE-USB_OTG-0460 detect 'A' removal
	464, // (m) PBASE-USB_OTG-0464 raise
	465  // (m) PBASE-USB_OTG-0465 lower
	};


	
//	
// CTestEngine implementation
//
CTestEngine* CTestEngine::NewL()
	{
	CTestEngine* self = new (ELeave) CTestEngine;
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}


CTestEngine::CTestEngine():
	iTestCaseIndex(0),
	iHelpRequested(EFalse)
	{

	}


CTestEngine::~CTestEngine()
	{
	LOG_FUNC
	// Destroy the test case controller
	if (iTestCaseController)
		{
		delete iTestCaseController;
		}
	// Destroy the test identity array and its contents
	iTestCasesIdentities.ResetAndDestroy();
	
	}
	
	
void CTestEngine::ConstructL()
	{
	LOG_FUNC
	TInt menuSelection(0);

	// Display information 
	test.Title();
	test.Start(_L("Test Engine Initiation v2.00 "));
	test.Printf(_L(">>\n"));
	test.Printf(_L(">>   T E S T   R U N \n"));
	test.Printf(_L(">>\n"));
	

	// Process the command line parameters for batch/etc
	TRAPD(err, ProcessCommandLineL());
	if (err != KErrNone)
		{
		User::Panic(_L("Test F/W Err"), KErrNoMemory);
		}
	
	if (iHelpRequested)
		{
		PrintUsage();
		User::Leave(-2);	// nothing to do!
		}

	// if no command-line, we use a menu UI
	if (!iTestCasesIdentities.Count())
		{
		RPointerArray<HBufC> testCaseNames;
		// no tests added, select ONE to run from the menu

		// list test cases (PRINT MENU) - in numeric order
		RTestFactory::ListRegisteredTestCases(testCaseNames);

		iTestCaseIndex = 0;	// be sure we go back to beginning of the collection!
		iTestCasesIdentities.ResetAndDestroy();
		
		test.Printf(_L("Please select 0 to %d\n"), RTestFactory::TestCaseCount()-1);
		test.Printf(_L("or 99<ENTER> to exit\n"));
		GetNumericInput(menuSelection);
		if ((menuSelection >=0) &&(menuSelection < RTestFactory::TestCaseCount()))
			{
			// add it to the list,and we can go
			TBuf<KTestCaseIdLength> aSelectionID;
			HBufC* tc = HBufC::NewLC(KTestCaseIdLength);
			
			// get name from index
			*tc = aSelectionID;
			*tc = *testCaseNames[menuSelection];

			iTestCasesIdentities.Append(tc);
			CleanupStack::Pop(tc);
			}
		testCaseNames.ResetAndDestroy();
		}
	
	if ((menuSelection < RTestFactory::TestCaseCount()) && (menuSelection>=0))
		{
		// Create the test case controller
		test.Printf(_L("Creating the test controller\n"));
		iTestCaseController = CTestCaseController::NewL(*this, ETrue);
		
		// Test-engine is non CActive class
		}
	else
		{
		// nothing to do, exit. USER aborted
		test.Printf(_L("Test run stopped by user, nothing to do.\n"));
		User::Leave(-2);
		}
	}
	

/* Displayed if used supplied no parameters, garbage, or a ? in the parameters
 */
void CTestEngine::PrintUsage()
	{
	test.Printf(_L("OTGDI Unit Test Suite.\n"));
	test.Printf(_L("Usage : t_otgdi.exe [/option] /G:<TESTNUM1>\n"));
	test.Printf(_L("  /ALL = add default test subset to List\n"));
	test.Printf(_L("  /G:<TESTNUM>  where <testname> is the test# to add \n"));
	test.Printf(_L("  /AUTO  = largely unattended operation\n"));
	test.Printf(_L("  /VERBOSE = test debugging info\n"));
	test.Printf(_L("  /LOOPO:<n> = Open/close repeat counter<n>\n"));
	test.Printf(_L("  /LOOPM:<n> = OOM HEAP_ALLOCS counter<n>\n"));
	test.Printf(_L("  /SLAVE = Test-peer server mode\n"));
	test.Printf(_L("  /PID:<n> = USB VID/PID in hex eg 2670\n"));
	test.Printf(_L("Valid test ID range 0456...0469\n"));
	test.Printf(_L("and 0675...0684 .\n"));
	test.Printf(_L("\n"));
	}
	
/** process the command-line, ; arguments appear in any order
 IN   : User::CommandLine()
 OUT  : iTestCasesIdentities
        iHelpRequested
 		gSemiAutomated
 		gVerboseOutput
 		gOpenIterations
 		gOOMIterations
 		gTestRoleMaster
 		gUSBVidPid
*/
void CTestEngine::ProcessCommandLineL()
	{
	// example t_otgdi.exe /ALL /G:0468 /VERBOSE
	TInt cmdLineLength(User::CommandLineLength());
	HBufC* cmdLine = HBufC::NewMaxLC(cmdLineLength);
	TPtr cmdLinePtr = cmdLine->Des();
	User::CommandLine(cmdLinePtr);
	TBool  tokenParsed(EFalse);

	TLex args(*cmdLine);
	args.SkipSpace(); // args are separated by spaces
	
	// first arg is the exe name, skip it
	TPtrC cmdToken = args.NextToken();
	HBufC* tc = HBufC::NewLC(KParameterTextLenMax);
	*tc = cmdToken;
	while (tc->Length())
		{
		tokenParsed = EFalse;
		
		// '/?' help wanted flag '?' or /? parameter
		TInt pos(0);
		if ((0== tc->FindF(_L("?"))) || (0==tc->FindF(_L("/?")))) 
			{
			iHelpRequested = ETrue;
			tokenParsed = ETrue;
			}	
		
		// '/ALL' parameter
		pos = tc->FindF(KArgAllTestCases);
		if (pos != KErrNotFound)
			{
			AddAllDefaultTests();
			tokenParsed = ETrue;
			}

		// '/AUTO'	
		pos = tc->FindF(KArgAutomatedTest);
		if (pos != KErrNotFound)
			{
			// skip some of the press-any key things
			test.Printf(_L("Test semi-automated mode.\n"));
			gSemiAutomated = ETrue;
			tokenParsed = ETrue;
			}

		// '/G:TESTNAME'
		pos = tc->FindF(KArgGoTestCase);
		if (pos != KErrNotFound)
			{ 
			HBufC* tcPart = HBufC::NewLC(KTestCaseIdLength);
			TPtrC testID = tc->Right(tc->Length() - pos - KArgGoTestCase().Length());

			LOG_VERBOSE2(_L("Parameter found:'%S'\n"), &testID);

			// Check if it is a test we know of in our suite, users may provide the full  
			// name "PBASE-USB_OTGDI-0466", or just the last 4 digits "0466", in such cases, fetch the full name
			if (!RTestFactory::TestCaseExists(testID))
				{ // try use just the test#part
				TPtr  tcDes = tcPart->Des();

				// build and add the full name
				tcDes.Format(KidFormatterS, &testID);
				if (!RTestFactory::TestCaseExists(tcDes))
					{
					
					test.Printf(_L("Test case does NOT Exist: '%lS'\n"), &testID);
					}
				else
					{ // only the number was supplied, copy the full name
					testID.Set(tcDes);
					}
				}
			// check that it's valid before adding it to the run-list
			if (RTestFactory::TestCaseExists(testID))
				{
				HBufC* testIdentity = HBufC::NewLC(KTestCaseIdLength);
				*testIdentity = testID;
				test.Printf(_L("Test case specified: %lS\n"), testIdentity);

				iTestCasesIdentities.Append(testIdentity);
				CleanupStack::Pop(testIdentity);
				}
			CleanupStack::PopAndDestroy(tcPart);
			tokenParsed = ETrue;
			}
			
		// '/VERBOSE' option	
		pos = tc->FindF(KArgVerboseOutput);
		if (pos != KErrNotFound)
			{ 
			gVerboseOutput = ETrue;
			tokenParsed = ETrue;
			
			// turn on logging of test Printf() output to serial debug/log at the same time
			test.SetLogged(ETrue);
			
			}

		// '/LOOPO:n' option (Set #times to run open/close tests amongst others)
		pos = tc->FindF(KArgSetOpenIterations);
		if (pos != KErrNotFound)
			{ 
			TPtrC iterationStr = tc->Right(tc->Length() - pos - KArgSetOpenIterations().Length());
			TLex  lex(iterationStr);
			lex.Val(gOpenIterations);
			MINMAX_CLAMPVALUE(gOpenIterations, OPEN_MINREPEATS, OPEN_MAXREPEATS);
			tokenParsed = ETrue;
			}

		// '/LOOPM:n' option (Set # of allocs to start at for OOM test)
		pos = tc->FindF(KArgSetOOMIterations);
		if (pos != KErrNotFound)
			{ 
			TPtrC iterationStr = tc->Right(tc->Length() - pos - KArgSetOOMIterations().Length());
			TLex  lex(iterationStr);
			lex.Val(gOOMIterations);
			MINMAX_CLAMPVALUE(gOOMIterations, OOM_MINREPEATS, OOM_MAXREPEATS);
			tokenParsed = ETrue;
			}
		
		
		// '/VID:nnnn' option (Set Symbian or other VID-Pid example /VID:0670)
		pos = tc->FindF(KArgOverrideVidPid);
		if (pos != KErrNotFound)
			{ 
			TPtrC vidpidStr = tc->Right(tc->Length() - pos - KArgOverrideVidPid().Length());
			TUint16 prodID;
			TLex  lex(vidpidStr);
			
			if (KErrNone == lex.Val(prodID, EHex))
				{
				if (prodID> 0xFFFF)
					prodID = 0xFFFF;
				tokenParsed = ETrue;
				LOG_VERBOSE2(_L(" accept param %04X \n\n"), prodID);
				gUSBVidPid = prodID; // replace the vid-pid with the user-supplied one 
				}
			else
				{
				// print error
				test.Printf(_L("Warning: VID+PID '%lS' not parsed .\n"), tc);
				}
			}
		
		// '/SLAVE' (peer)
		pos = tc->FindF(KArgSetRoleSlave);
		if (pos != KErrNotFound)
			{ 
			gTestRoleMaster = EFalse;
			tokenParsed = ETrue;
			}
		// '/MASTER' - default role
		pos = tc->FindF(KArgSetRoleMaster); // note that master is the default role, so this parameter is optional
		if (pos != KErrNotFound)
			{ 
			gTestRoleMaster = ETrue;
			tokenParsed = ETrue;
			}		
		
		if (!tokenParsed)
			{
			// warn about unparsed parameter
			test.Printf(_L("Warning: '%lS'??? not parsed\n"), tc);
			iHelpRequested = ETrue;
			}
			
		// next parameter
		*tc = args.NextToken();
		}
	CleanupStack::PopAndDestroy(tc);
	CleanupStack::PopAndDestroy(cmdLine);
	}


/** Add all default tests to the front of the test-list so we run them all in sequence
*/	
void CTestEngine::AddAllDefaultTests()
	{
	test.Printf(_L("Adding default set test cases\n"));
	//
	TInt index(0);
	while (index < sizeof(KAllDefaultTestIDs)/sizeof(KAllDefaultTestIDs[0]))
		{
		// allocate heap string
		HBufC* tc(NULL);
		TRAPD(err, tc = HBufC::NewL(KTestCaseIdLength))
		if (err != KErrNone)
			{
			User::Panic(_L("Test F/W Err"), KErrNoMemory);
			}
		TPtr  tcDes = tc->Des();

		// build and add it
		tcDes.Format(KidFormatter, KAllDefaultTestIDs[index]);
		iTestCasesIdentities.Append(tc);
		index++;
		}
	}


/* Return subsequent test case IDs from the test run-list KerrNotFound = end of list.
 */ 	
TInt CTestEngine::NextTestCaseId(TDes& aTestCaseId)
	{
	if (iTestCaseIndex < iTestCasesIdentities.Count())
		{
		aTestCaseId = *iTestCasesIdentities[iTestCaseIndex++];
		return KErrNone;
		}
	else
		{
		return KErrNotFound;
		}
	}

/////////////////////////////////////////////////////////////////////////////
// utility functions


void CTestEngine::GetNumericInput(TInt &aNumber)
	{
	TUint value(0);
	TUint digits(0);
	TKeyCode key = (TKeyCode) 0;

	aNumber = -1;
	while ( key != EKeyEnter )
		{
		key = test.Getch();

		if ( ( key >= '0' ) && ( key <= '9' ) )
			{
			test.Printf(_L("%c"),key);
			
			value = ( 10 * value ) + ( key - '0' );
			digits++;
			} else 
			{ // very basic keyboard processing, backspace
				if (key == EKeyBackspace)
				{
				value = value/10;
				digits--;
				test.Printf(_L("\r    \r%d"), value);
				}
			}
		}

	if (digits > 0)
		{
		aNumber = value;
		}
	test.Printf(_L("\n"));
	}


/** Print a report at the end of a test run of all PASSED tests, Note: If a 
 test fails, the framework gets Panic'd */
void CTestEngine::Report()
	{
	TBuf<KTestCaseIdLength> aTestCaseId;
	test.Printf(_L("============================\n"));
	test.Printf(_L("PASSED TESTS:\n"));
	// itterate our list of tests to perform
	ResetTestCaseIndex();
	while (KErrNone == NextTestCaseId(aTestCaseId))
		{
		test.Printf(_L("%S\n"), &aTestCaseId);
		}
	}
	
	
void CTestEngine::DoCancel()
	{
	LOG_FUNC
	test.Console()->ReadCancel();	
	}
		
	
TInt CTestEngine::RunError(TInt aError)
	{
	return aError;
	}