os/mm/mmtestenv/mmtestfw/recog/TestFrameworkRecog.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <fbs.h>
sl@0
    17
#include "TestFrameworkRecog.h"
sl@0
    18
#include "TestFrameworkMain.h"
sl@0
    19
sl@0
    20
#ifdef __WINS__
sl@0
    21
#include <windows.h>	// for ExitProcess
sl@0
    22
#endif // __WINS__
sl@0
    23
sl@0
    24
GLREF_C void StartupL();
sl@0
    25
const TInt KThreadStackSize=0x2000;			//  8KB
sl@0
    26
const TInt KThreadInitHeapSize=0x1000;		//  4KB
sl@0
    27
const TInt KThreadMaxHeapSize=0x1000000;	// 16MB
sl@0
    28
const TInt KThreadStartupDelay=30000000;	// 30 seconds
sl@0
    29
const TInt KMaxLineLength=256;				// max length of config file line
sl@0
    30
_LIT(KLitConfigFileName, "C:\\MM\\AutorunTests.cfg");
sl@0
    31
sl@0
    32
//
sl@0
    33
sl@0
    34
CTestFrameworkRecognizer::CTestFrameworkRecognizer()
sl@0
    35
	: CApaDataRecognizerType(KUidTestFrameworkRecognizer, CApaDataRecognizerType::ENormal)
sl@0
    36
	{
sl@0
    37
	}
sl@0
    38
sl@0
    39
CTestFrameworkRecognizer::~CTestFrameworkRecognizer()
sl@0
    40
	{
sl@0
    41
	delete iTestActive;
sl@0
    42
	}
sl@0
    43
sl@0
    44
//
sl@0
    45
// CApaDataRecognizerType stuff...
sl@0
    46
TUint CTestFrameworkRecognizer::PreferredBufSize()
sl@0
    47
	{
sl@0
    48
	return 0;
sl@0
    49
	}
sl@0
    50
sl@0
    51
TDataType CTestFrameworkRecognizer::SupportedDataTypeL(TInt /*aIndex*/) const
sl@0
    52
	{
sl@0
    53
	return TDataType();
sl@0
    54
	}
sl@0
    55
sl@0
    56
void CTestFrameworkRecognizer::DoRecognizeL(const TDesC& /*aName*/, const TDesC8& /*aBuffer*/)
sl@0
    57
	{
sl@0
    58
	}
sl@0
    59
sl@0
    60
//
sl@0
    61
// Entry point of recognizer
sl@0
    62
EXPORT_C CApaDataRecognizerType* CreateRecognizer()
sl@0
    63
	{
sl@0
    64
	CTestFrameworkRecognizer* self = new CTestFrameworkRecognizer();
sl@0
    65
	TRAPD(err, self->DoCreateL());
sl@0
    66
	return self;
sl@0
    67
	}
sl@0
    68
sl@0
    69
void CTestFrameworkRecognizer::DoCreateL()
sl@0
    70
	{
sl@0
    71
	// Open the config file
sl@0
    72
	LoadConfigFileL(KLitConfigFileName);
sl@0
    73
sl@0
    74
	// If the RUN_SCRIPT command is present in the config file, run each test in a separate thread
sl@0
    75
	if (iRunScript)
sl@0
    76
		{
sl@0
    77
		// Create active object waiting on thread death
sl@0
    78
		iTestActive = new(ELeave) CTestFrameworkRecogActive(iTestScriptArray);	// Takes ownership of iTestScriptArray
sl@0
    79
sl@0
    80
		// Create the first test thread
sl@0
    81
		iTestActive->CreateNextTestThread();
sl@0
    82
		}
sl@0
    83
	}
sl@0
    84
sl@0
    85
void CTestFrameworkRecognizer::LoadConfigFileL(const TDesC& aFileName)
sl@0
    86
	{
sl@0
    87
	RFs fs;
sl@0
    88
	User::LeaveIfError(fs.Connect());
sl@0
    89
	CleanupClosePushL(fs);
sl@0
    90
sl@0
    91
	TEntry entry;
sl@0
    92
	User::LeaveIfError(fs.Entry(aFileName, entry));
sl@0
    93
sl@0
    94
	RFile file;
sl@0
    95
	User::LeaveIfError(file.Open(fs, aFileName, EFileRead));
sl@0
    96
	CleanupClosePushL(file);
sl@0
    97
sl@0
    98
	TInt size;
sl@0
    99
	User::LeaveIfError(file.Size(size));
sl@0
   100
	TUint8* fileData = (TUint8*)User::AllocLC(size);
sl@0
   101
	TPtr8 ptr(fileData, 0, size);
sl@0
   102
	User::LeaveIfError(file.Read(ptr));
sl@0
   103
sl@0
   104
	iTestScriptArray = new(ELeave) CTestScriptArray(4);
sl@0
   105
sl@0
   106
	// Process the config file
sl@0
   107
	TLex8 lex(ptr);
sl@0
   108
	while (!lex.Eos())
sl@0
   109
		{
sl@0
   110
		// skip any spaces
sl@0
   111
		while (lex.Peek() == ' ')
sl@0
   112
			lex.Inc();
sl@0
   113
		// mark the start of the line
sl@0
   114
		lex.Mark();
sl@0
   115
		// move to the next
sl@0
   116
		while (!lex.Eos() && lex.Peek() != '\n')
sl@0
   117
			lex.Inc();
sl@0
   118
		// step over \n
sl@0
   119
		if (lex.Peek() == '\n' )
sl@0
   120
			lex.Inc();
sl@0
   121
sl@0
   122
		// Process line
sl@0
   123
		TPtrC8 linePtr = lex.MarkedToken();
sl@0
   124
		ProcessLineL(linePtr);
sl@0
   125
		}
sl@0
   126
	CleanupStack::PopAndDestroy(fileData);
sl@0
   127
	CleanupStack::PopAndDestroy(2);	// file, fs
sl@0
   128
	}
sl@0
   129
sl@0
   130
void CTestFrameworkRecognizer::ProcessLineL(const TDesC8& aLine)
sl@0
   131
	{
sl@0
   132
	ASSERT(aLine.Length() <= KMaxLineLength);
sl@0
   133
	TBuf<KMaxLineLength> buf;
sl@0
   134
	buf.Copy(aLine);
sl@0
   135
	if (buf.Find(_L("//"))==0)
sl@0
   136
		{
sl@0
   137
		// ignore comments
sl@0
   138
		}
sl@0
   139
	else
sl@0
   140
		{
sl@0
   141
		// Get the script path and startup delay
sl@0
   142
		TLex lex(buf);
sl@0
   143
		if (!iRunScript)
sl@0
   144
			{
sl@0
   145
			if (lex.NextToken().Compare(_L("RUN_SCRIPT")) == 0)
sl@0
   146
				iRunScript = ETrue;
sl@0
   147
			}
sl@0
   148
		else
sl@0
   149
			{
sl@0
   150
			// Parse the parameters
sl@0
   151
			TTestScriptInfo info;
sl@0
   152
			info.iScriptPath = lex.NextToken();
sl@0
   153
			info.iThreadStartupDelay = 0;
sl@0
   154
sl@0
   155
			TPtrC token(lex.NextToken());
sl@0
   156
			while (token.Length())
sl@0
   157
				{
sl@0
   158
				if (token[0] == '-')
sl@0
   159
					{
sl@0
   160
					info.iParams.Append(token);
sl@0
   161
					info.iParams.Append(' ');
sl@0
   162
					}
sl@0
   163
				else
sl@0
   164
					{
sl@0
   165
					// Assume this to be the startup delay
sl@0
   166
					TLex tokenLex(token);
sl@0
   167
					User::LeaveIfError(tokenLex.Val(info.iThreadStartupDelay));
sl@0
   168
					if (info.iThreadStartupDelay < 0)
sl@0
   169
						info.iThreadStartupDelay = 0;
sl@0
   170
					}
sl@0
   171
				token.Set(lex.NextToken());
sl@0
   172
				}
sl@0
   173
sl@0
   174
			// Add the script info
sl@0
   175
			if (info.iScriptPath.Length())
sl@0
   176
				iTestScriptArray->AppendL(info);
sl@0
   177
			}
sl@0
   178
		}
sl@0
   179
	}
sl@0
   180
sl@0
   181
//
sl@0
   182
// CTestFrameworkRecogActive
sl@0
   183
CTestFrameworkRecogActive::CTestFrameworkRecogActive(CTestScriptArray* aTestScriptArray)
sl@0
   184
	: CActive(EPriorityStandard), iTestScriptArray(aTestScriptArray)
sl@0
   185
	{
sl@0
   186
	CActiveScheduler::Add(this);
sl@0
   187
	iCurrentScript = -1;
sl@0
   188
	}
sl@0
   189
sl@0
   190
CTestFrameworkRecogActive::~CTestFrameworkRecogActive()
sl@0
   191
	{
sl@0
   192
	delete iTestScriptArray;
sl@0
   193
	}
sl@0
   194
sl@0
   195
TInt CTestFrameworkRecogActive::CreateNextTestThread()
sl@0
   196
	{
sl@0
   197
	// Create the next test in a separate thread
sl@0
   198
	iCurrentScript++;
sl@0
   199
	RThread thread;
sl@0
   200
	TBuf<16> threadName;
sl@0
   201
	threadName.Format(_L("TFR_THREAD_%d"), iCurrentScript);
sl@0
   202
sl@0
   203
	TInt err = thread.Create(threadName, &StartTestThreadFn, KThreadStackSize,
sl@0
   204
							 &User::Heap(), this);
sl@0
   205
sl@0
   206
	if (err == KErrNone)
sl@0
   207
		{
sl@0
   208
		thread.Logon(iStatus);
sl@0
   209
		thread.Resume();
sl@0
   210
		SetActive();
sl@0
   211
		}
sl@0
   212
	return err;
sl@0
   213
	}
sl@0
   214
sl@0
   215
void CTestFrameworkRecogActive::DoCancel()
sl@0
   216
	{
sl@0
   217
	}
sl@0
   218
sl@0
   219
void CTestFrameworkRecogActive::RunL()
sl@0
   220
	{
sl@0
   221
	// This will run when the thread created in CreateNextTestThreadL dies
sl@0
   222
	//
sl@0
   223
	TInt err = KErrNone;
sl@0
   224
	if (iCurrentScript < (iTestScriptArray->Count() - 1))
sl@0
   225
		{
sl@0
   226
		err = CreateNextTestThread();
sl@0
   227
		}
sl@0
   228
	else
sl@0
   229
		{
sl@0
   230
		// Tests finished
sl@0
   231
		delete iTestScriptArray;
sl@0
   232
		iTestScriptArray = NULL;
sl@0
   233
#ifdef __WINS__
sl@0
   234
		// Cause the emulator to exit
sl@0
   235
		ExitProcess(0);
sl@0
   236
#endif // __WINS__
sl@0
   237
		}
sl@0
   238
	}
sl@0
   239
sl@0
   240
TInt CTestFrameworkRecogActive::StartTestThreadFn(TAny* aPtr)
sl@0
   241
	{
sl@0
   242
	CTestFrameworkRecogActive* self = static_cast<CTestFrameworkRecogActive*>(aPtr);
sl@0
   243
	TRAPD(err, self->DoStartTestThreadL());
sl@0
   244
	return err;
sl@0
   245
	}
sl@0
   246
sl@0
   247
void CTestFrameworkRecogActive::DoStartTestThreadL()
sl@0
   248
	{
sl@0
   249
	// Create the thread and wait until it's finished
sl@0
   250
	RThread thread;
sl@0
   251
	TBuf<16> threadName;
sl@0
   252
	threadName.Format(_L("TESTFRMRECOG_%d"), iCurrentScript);
sl@0
   253
sl@0
   254
	TInt err = thread.Create(threadName, &ThreadFunc, KThreadStackSize,
sl@0
   255
							 &User::Heap(), this);
sl@0
   256
sl@0
   257
	if (err == KErrNone)
sl@0
   258
		{
sl@0
   259
		RSemaphore sem;
sl@0
   260
		err = sem.CreateGlobal(KRecogSemaphoreName, 0);
sl@0
   261
		if (err == KErrAlreadyExists)
sl@0
   262
			err = sem.OpenGlobal(KRecogSemaphoreName);
sl@0
   263
		if (err == KErrNone)
sl@0
   264
			{
sl@0
   265
			// Start the thread and wait for it to signal us that it's finished
sl@0
   266
			thread.Resume();
sl@0
   267
			sem.Wait();
sl@0
   268
			}
sl@0
   269
		}
sl@0
   270
	User::LeaveIfError(err);
sl@0
   271
	}
sl@0
   272
sl@0
   273
sl@0
   274
TInt CTestFrameworkRecogActive::ThreadFunc(TAny* aPtr)
sl@0
   275
	{
sl@0
   276
	CTrapCleanup* cleanup = CTrapCleanup::New(); // get clean-up stack
sl@0
   277
	CTestFrameworkRecogActive* self = static_cast<CTestFrameworkRecogActive*>(aPtr);
sl@0
   278
	TRAPD(err, self->DoThreadFuncL());
sl@0
   279
	delete cleanup; // destroy clean-up stack
sl@0
   280
	return err;
sl@0
   281
	}
sl@0
   282
sl@0
   283
void CTestFrameworkRecogActive::DoThreadFuncL()
sl@0
   284
	{
sl@0
   285
	// Run the test script, using filename held in iScriptPath
sl@0
   286
	CActiveScheduler* scheduler=new(ELeave) CActiveScheduler;
sl@0
   287
	CleanupStack::PushL(scheduler);
sl@0
   288
	CActiveScheduler::Install(scheduler);
sl@0
   289
sl@0
   290
// Hurricane emulator only - start all services which we require to run tests.
sl@0
   291
// Future enhancement :- add these startups to TestUtils
sl@0
   292
#if defined(__WINS__)
sl@0
   293
	#ifndef EXCLUDE_FOR_UNITTEST
sl@0
   294
	FbsStartup();
sl@0
   295
	#endif // EXCLUDE_FOR_UNITTEST
sl@0
   296
#endif
sl@0
   297
sl@0
   298
	// Get the current script
sl@0
   299
	const TTestScriptInfo& script = iTestScriptArray->At(iCurrentScript);
sl@0
   300
sl@0
   301
	// Delay for several seconds to allow vital bits of the emulator to start up (window server bits)
sl@0
   302
	User::After(script.iThreadStartupDelay);
sl@0
   303
sl@0
   304
	// Format the parameter to be passed to the test framework
sl@0
   305
	TFileName args;
sl@0
   306
	if (script.iParams.Length())
sl@0
   307
		{
sl@0
   308
		// Add the params
sl@0
   309
		args.Append(script.iParams);
sl@0
   310
		args.Append(' ');
sl@0
   311
		}
sl@0
   312
	args.Append(script.iScriptPath);
sl@0
   313
sl@0
   314
	// Run the script
sl@0
   315
	CTestFrameworkMain* tester = CTestFrameworkMain::NewLC();
sl@0
   316
	tester->StartTestingL(args);
sl@0
   317
sl@0
   318
	CleanupStack::PopAndDestroy(2, scheduler);	// tester, scheduler
sl@0
   319
	}
sl@0
   320
sl@0
   321