genericservices/taskscheduler/Test/Robustness/TC_TSCH_ROBUSTNESS.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericservices/taskscheduler/Test/Robustness/TC_TSCH_ROBUSTNESS.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,583 @@
+// 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:
+//
+
+#include <csch_cli.h>
+#include "Thelpers.h"
+
+#include <e32base.h>
+#include <e32test.h>
+#include <f32file.h>
+#include <s32file.h>
+#include <e32property.h>
+#include <schinfointernal.h>
+#include "TestUtils.h"
+
+_LIT(KTestName,	"Task Scheduler Robustness Test");
+_LIT(KTaskScheduler, "schexe");
+
+RTest	TheTest(KTestName);
+
+typedef CArrayFixFlat<TTaskInfo>			CTaskInfoArray;
+typedef CArrayFixFlat<TSchedulerItemRef>    CSchItemRefArray;
+typedef CArrayFixFlat<TTaskSchedulerCondition>	CSchConditionArray;
+
+static RScheduler	TheScheduler;
+static CTrapCleanup*	TheCleanup;
+static RFs			TheFsSession;
+
+const TInt KTestKey1 = 1;
+
+_LIT(KSeparator, "|"); // Invalid filepath char used to separate filenames
+
+// This function launches the TPropertyDefine process which
+//	has WriteDeviceData Capabilities enabling it to create the P&S 
+//	variables used by this test.
+static void LaunchHelperL(TUid aCategory, TInt aKey, TInt aAttr)
+	{
+	_LIT(KConditionHelper, "TPropertyDefine");
+	TRequestStatus stat;
+	RProcess p;
+	
+	TBuf<32> args;
+	args.AppendNum(aCategory.iUid);
+	args.Append(KSeparator);
+	args.AppendNum(aKey);
+	args.Append(KSeparator);
+	args.AppendNum(aAttr);
+	
+	User::LeaveIfError(p.Create(KConditionHelper, args,EOwnerProcess));
+	
+	// Asynchronous logon: completes when process terminates with process exit code
+	p.Logon(stat);
+	p.Resume();
+
+	User::WaitForRequest(stat);
+	TInt exitReason = p.ExitReason();
+	p.Close();
+	User::LeaveIfError(exitReason);
+	}
+	
+	
+static void CreateTestVariables()
+	{
+	LaunchHelperL(KUidSystemCategory, KTestKey1,RProperty::EInt);
+	}	
+
+static void ResetVariablesL(TInt aKey1Val)
+	{
+	User::LeaveIfError(RProperty::Set(KUidSystemCategory, KTestKey1,aKey1Val));		
+	}
+	
+	
+// single condition with default time set to 1 year in the future
+static TInt CreateScheduleL(TSchedulerItemRef& aRef, 
+									RScheduler& aScheduler,
+									const TUid& aConditionUID,
+									TUint aConditionUInt)
+	{
+	aRef.iName = _L("Schedule created using CreateScheduleSingle");
+
+	CSchConditionArray* conditionList = new (ELeave) CSchConditionArray(1);
+	CleanupStack::PushL(conditionList);
+	
+	//create a single condition
+	TTaskSchedulerCondition condition1;
+	condition1.iCategory = aConditionUID;
+	condition1.iKey		= aConditionUInt;
+	condition1.iState	= 10;
+	condition1.iType	= TTaskSchedulerCondition::EEquals;
+	
+	conditionList->AppendL(condition1);
+		
+	//create a persistent schedule
+	TTime time = SchSvrHelpers::TimeBasedOnOffset(0, 0, 0, 0, 0, 1); //1 year in the future
+	TInt res = aScheduler.CreatePersistentSchedule(aRef, *conditionList, time);
+	CleanupStack::PopAndDestroy(); // conditionList
+	return res;
+	}
+
+//Add a single task to a schedule	
+static TInt AddTaskToScheduleL(const TDesC& aName, 
+									TInt& aNewId, 
+									TInt aScheduleId, 
+									RScheduler& aScheduler)
+	{
+	TTaskInfo taskInfo;
+	taskInfo.iTaskId = aNewId;
+	taskInfo.iName = aName;
+	taskInfo.iPriority = 2;
+	taskInfo.iRepeat = 0;
+	HBufC* data = _L("the data").AllocLC();
+	TInt res = aScheduler.ScheduleTask(taskInfo, *data, aScheduleId);
+	aNewId = taskInfo.iTaskId;
+
+	CleanupStack::PopAndDestroy(); // data
+	return res;
+	}
+	
+	
+static TInt ScheduleTaskL()
+	{
+	//reset the p&s variables before creating the schedule
+	ResetVariablesL(0);
+	
+	//Create a schedule
+	TSchedulerItemRef ref1;
+	TheTest.Printf(_L("Create a schedule\n"));
+	TInt res = CreateScheduleL(ref1, TheScheduler, KUidSystemCategory, KTestKey1);
+	TEST2(res, KErrNone);
+	
+	//Add task to the schedule
+	TInt task1 = 0;
+	_LIT(KName1, "Test Task");
+	TheTest.Printf(_L("Schedule a task\n"));
+
+	res = AddTaskToScheduleL(KName1, task1, ref1.iHandle, TheScheduler);
+	TEST2(res, KErrNone);
+	 
+	return res;	
+	}
+	
+static void ExecuteTaskL()
+	{
+	TheTest.Printf(_L("Execute Task\n"));
+	//Set property causing schedule to be run
+	User::LeaveIfError(RProperty::Set(KUidSystemCategory, KTestKey1,10));
+	
+	//Pause to wait for the task to be executed
+	SchSvrHelpers::Pause(TheTest, 2);
+	
+	}
+
+static TInt ScheduleAndExecuteTaskL()
+	{
+	TInt res = ScheduleTaskL();
+
+	ExecuteTaskL();
+	 
+	return res;	
+	}
+
+LOCAL_C void AddTaskFunctionL()
+	{
+	RScheduler	localScheduler;
+	// Connect to the server
+	TInt res = localScheduler.Connect();
+	TEST2(res, KErrNone);
+	//Schedule a task and execute it
+	//reset the p&s variables before creating the schedule
+	ResetVariablesL(0);
+		
+	//Create a schedule
+	TSchedulerItemRef ref1;
+	ref1.iName = _L("Schedule created using CreateScheduleSingle");
+	CSchConditionArray* conditionList = new (ELeave) CSchConditionArray(1);
+	CleanupStack::PushL(conditionList);
+		
+	//create a single condition
+	TTaskSchedulerCondition condition1;
+	condition1.iCategory = KUidSystemCategory;
+	condition1.iKey		= KTestKey1;
+	condition1.iState	= 10;
+	condition1.iType	= TTaskSchedulerCondition::EEquals;
+			
+	conditionList->AppendL(condition1);
+				
+	//create a persistent schedule
+	TTime time = SchSvrHelpers::TimeBasedOnOffset(0, 0, 0, 0, 0, 1); //1 year in the future
+	res = localScheduler.CreatePersistentSchedule(ref1, *conditionList, time);
+	CleanupStack::PopAndDestroy(); // conditionList
+			
+	//Add task to the schedule
+	TInt task1 = 0;
+	_LIT(KName1, "Test Task");
+		
+	TTaskInfo taskInfo;
+	taskInfo.iTaskId = task1;
+	taskInfo.iName = KName1;
+	taskInfo.iPriority = 2;
+	taskInfo.iRepeat = 0;
+	HBufC* data = _L("the data").AllocLC();
+
+	TInt ret = localScheduler.ScheduleTask(taskInfo, *data, ref1.iHandle);
+	TEST2(ret, 0);//EPanicNotRegistered == 0
+		
+	task1 = taskInfo.iTaskId;
+
+	CleanupStack::PopAndDestroy(); // data
+		
+	//Tidying up so next test will be clear.
+	SchSvrHelpers::DeleteAllSchedulesL(localScheduler);
+
+	localScheduler.Close();
+	}
+
+// Helper function for DEF124488 
+LOCAL_C TInt TestPanicThread(TAny*)
+	{
+	CTrapCleanup* cleanup = CTrapCleanup::New();
+	if(!cleanup)
+		return KErrNoMemory;
+	
+
+	TRAPD(err,AddTaskFunctionL())
+	TEST2(err,KErrNone);
+	
+	delete cleanup;
+	return KErrNone;
+	}
+
+/**	
+@SYMTestCaseID 	SYSLIB-SCHSVR-CT-3369
+@SYMTestCaseDesc	Test deletion of temporary files with non existent client
+@SYMTestPriority	High
+@SYMTestActions 	Schedule a task with a client that does not exist.  
+					Ensure that all temporary files are deleted after 
+					schedule excecutes
+@SYMTestExpectedResults All temporary files should be deleted by task scheduler
+@SYMDEF 		 PDEF101876
+*/
+static void DoTest1L()
+	{	
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-3369 Test handling of non existent client "));	
+	// Connect to the server
+	TheTest.Next(_L("===== Connect to Scheduler ====="));
+	TInt res = TheScheduler.Connect();
+	TEST2(res, KErrNone);
+	
+	// Register a client with the server - this client does not exist
+	TheTest.Next(_L("===== Registering Client ====="));
+	res = SchSvrHelpers::RegisterNonExistentClient(TheScheduler);
+	TEST2(res, KErrNone);
+
+	//Schedule a task and execute it
+	ScheduleAndExecuteTaskL();
+	
+	// Check for left task files after scheduled tasks completed
+	// To access private data cage, uses SchSvrHelplers::CheckTaskFilesL()
+	TheTest.Next(_L("Now checking no files left when tasks completed"));
+	TInt err = SchSvrHelpers::CheckTaskFilesL();
+	
+	// If there's any task files left, test fails with error code KErrGeneral
+	TEST(err == KErrNone);
+	TheTest.Next(_L("All files deleted as expected..."));
+
+	//Tidying up so next test will be clear.
+	TheTest.Next(_L("Delete all schedules"));
+	SchSvrHelpers::DeleteAllSchedulesL(TheScheduler);
+
+	TheScheduler.Close();
+
+	}
+	
+/**
+@SYMTestCaseID 	SYSLIB-SCHSVR-CT-3370
+@SYMTestCaseDesc	Test deletion of temporary files with faulty client
+@SYMTestPriority	High
+@SYMTestActions 	Schedule a task with a client that panics and does not 
+					release the temporary file handle. 
+					Ensure that all temporary files are deleted after schedule excecutes
+@SYMTestExpectedResults All temporary files should be deleted by task scheduler
+@SYMDEF 		 PDEF101876
+*/	
+static void DoTest2L()
+	{
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-3370 Test handling of panicing client "));
+	
+	// Connect to the server
+	TheTest.Next(_L("===== Connect to Scheduler ====="));
+	TInt res = TheScheduler.Connect();
+	TEST2(res, KErrNone);
+	
+	// Register a client with the server - this client panics
+	//after calling RFile::AdoptFromClient
+	TheTest.Next(_L("===== Registering Client ====="));
+	res = SchSvrHelpers::RegisterPanicingClient(TheScheduler);
+	TEST2(res, KErrNone);
+		
+	//Schedule a task and execute it - we expect the client to panic
+	ScheduleAndExecuteTaskL();
+	
+	// Check for left task files after scheduled tasks completed
+	// To access private data cage, uses SchSvrHelplers::CheckTaskFilesL()
+	TheTest.Next(_L("Now checking no files left when tasks completed"));
+	TInt err = SchSvrHelpers::CheckTaskFilesL();
+
+	// If there's any task files left, test fails with error code KErrGeneral
+	TEST(err == KErrNone);	
+	
+	TheTest.Next(_L("All files deleted as expected..."));
+
+	//Tidying up so next test will be clear.
+	TheTest.Next(_L("Delete all schedules"));
+	SchSvrHelpers::DeleteAllSchedulesL(TheScheduler);
+
+	TheScheduler.Close();
+	}
+
+/**
+@SYMTestCaseID 	SYSLIB-SCHSVR-CT-3371
+@SYMTestCaseDesc	Test deletion of temporary files on task scheduler startup
+@SYMTestPriority	High
+@SYMTestActions 	Create temporary files in the task schedulers private data cage.
+					Start the task scheduler and verify that these files are deleted.
+@SYMTestExpectedResults All temporary files should be deleted by task scheduler on startup
+@SYMDEF 		 PDEF101876
+*/	
+static void DoTest3L()
+	{	
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-3371 Test deletion of temporary files on startup "));
+	
+	//Connect to the scheduler
+	TInt res = TheScheduler.Connect();
+	TEST2(res, KErrNone);
+
+ 	// Kill the server to ensure we restart it when we connect
+	res = CleanupHelpers::KillProcess(KTaskScheduler);
+	TEST2(res, KErrNone);
+ 	TheScheduler.Close();
+ 	
+	// Create task files to test cleanup
+	// To access private data cage, uses SchSvrHelplers::CreateTaskFilesL()
+	TheTest.Next(_L("Creating dummy task files"));
+	res = SchSvrHelpers::CreateTaskFilesL();
+
+	//Restart the scheduler which should clean up temp files on startup
+	TheTest.Next(_L("===== Connect to Scheduler ====="));
+	res = TheScheduler.Connect();
+	TEST2(res, KErrNone);
+	
+	//wait for the server to start up
+	SchSvrHelpers::Pause(TheTest, 2);
+		
+	TheScheduler.Close();
+	
+	// Check for left task files after scheduled tasks completed
+	// To access private data cage, uses SchSvrHelplers::CheckTaskFilesL()
+	TheTest.Next(_L("Now checking no files left after task scheduler starts"));
+	res = SchSvrHelpers::CheckTaskFilesL();
+	
+	TEST2(res, KErrNone);
+	
+	TheTest.Next(_L("All files deleted as expected..."));
+	}
+
+/**
+@SYMTestCaseID 		SYSLIB-SCHSVR-CT-3402
+@SYMTestCaseDesc	Test memory cleanup on Task Scheduler exit
+@SYMTestPriority	High
+@SYMTestActions 	Start the scheduler and register a client.
+					Execute a schedule and then terminate the scheduler.
+					When the scheduler is restarted it should exit as there are no
+					pending schedules. On exit all allocated memory should be freed	
+@SYMTestExpectedResults All allocated memory should be freed when the scheduler exits
+@SYMDEF 		 DEF102414
+*/	
+static void DoTest4L()
+	{	
+	__UHEAP_MARK;
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-3402 Test memory cleanup on Task Scheduler exit "));
+	
+	// Connect to the server
+	TheTest.Next(_L("===== Connect to Scheduler ====="));
+	TInt res = TheScheduler.Connect();
+	TEST2(res, KErrNone);
+	
+	// Register a client with the server
+	TheTest.Next(_L("===== Registering Client ====="));
+	res = SchSvrHelpers::RegisterClientL(TheScheduler);
+	TEST2(res, KErrNone);
+	
+	//Schedule a task and execute it
+	ScheduleAndExecuteTaskL();
+	
+ 	// Kill the server
+	res = CleanupHelpers::KillProcess(KTaskScheduler);
+	TEST2(res, KErrNone);
+	
+ 	TheScheduler.Close();
+	
+	//Restarting with a registered client and no schedule should
+	//cause the server to exit.  Ther server should free all allocated
+	//memory.  If all memory is not freed, heap check macros within
+	// the task scheduler code will cause a panic 
+	SchSvrHelpers::LaunchTaskSchedulerL();
+	
+	//wait for the server to exit
+	SchSvrHelpers::Pause(TheTest, 2);
+	
+	//Verify that the server has already exited - there are two valid 
+	//error codes depending on how quickly the process is cleaned up
+	//KErrDied - Process is dead but hasn't been cleaned up yet by the kernel
+	//KErrNotFound - Process has been cleaned up
+	res = CleanupHelpers::KillProcess(KTaskScheduler);
+	
+	TEST((res == KErrDied)||(res == KErrNotFound));
+	
+	__UHEAP_MARKEND;
+
+	TheTest.Next(_L("All memory freed..."));
+	}
+	
+	
+/**
+@SYMTestCaseID 		SYSLIB-SCHSVR-CT-3412
+@SYMTestCaseDesc	Test Task Scheduler startup with pending schedule
+@SYMTestPriority	High
+@SYMTestActions 	Start the scheduler and register a client.
+					Create a scheduled task and then terminate the scheduler without executing the task.
+					When the scheduler is restarted it should not exit as there is a 
+					pending schedule. Verify that the scheduler is still active by executing
+					the schedule
+@SYMTestExpectedResults	The task scheduler should not exit and the schedule should execute
+@SYMDEF 		 DEF102414
+*/	
+static void DoTest5L()
+	{
+	__UHEAP_MARK;
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-3412 Test Task Scheduler startup with pending schedule "));
+	
+	// Connect to the server
+	TheTest.Next(_L("===== Connect to Scheduler ====="));
+	TInt res = TheScheduler.Connect();
+	TEST2(res, KErrNone);
+	
+	// Register a client with the server
+	TheTest.Next(_L("===== Registering Client ====="));
+	res = SchSvrHelpers::RegisterClientL(TheScheduler);
+	TEST2(res, KErrNone);
+	
+	//Schedule a task
+	ScheduleTaskL();
+	
+ 	// Kill the server
+	res = CleanupHelpers::KillProcess(KTaskScheduler);
+	TEST2(res, KErrNone);
+ 	TheScheduler.Close();
+ 	
+ 	TheTest.Next(_L("Create Task notification semaphore"));
+	//initialise task notification semaphore
+	STaskSemaphore sem;
+	sem.CreateL();
+	
+	//Restart the scheduler - task scheduler should not exit as there is a 
+	//pending schedule
+	res = SchSvrHelpers::LaunchTaskSchedulerL();
+	TEST2(res, KErrNone);
+	
+	//Execute task and wait for it to run - this would not succeed
+	//if task scheduler had exited above
+	ExecuteTaskL();
+	TEST2(STaskSemaphore::WaitL(KDefaultTimeout), KErrNone); 
+	
+	//Kill the process and verify that the scheduler was active
+	//If the task scheduler isnt active when we try to kill it
+	//KillProcess would return KErrDied
+	res = CleanupHelpers::KillProcess(KTaskScheduler);
+	TEST2(res, KErrNone);
+	
+	//close handle to semaphore
+	sem.Close();
+
+	__UHEAP_MARKEND;	
+	
+	}
+
+/**	
+@SYMTestCaseID 	SYSLIB-SCHSVR-CT-4010
+@SYMTestCaseDesc	Test that adding a task using an unregistered client panics the client and does not crash the server.
+@SYMTestPriority	High
+@SYMTestActions 	Schedule a task with a client that has not been registered.  
+@SYMTestExpectedResults Client should be panicked.
+@SYMDEF 		DEF124488 
+*/
+static void DoTest6L()
+	{	
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-4010 Test handling of unregistered client Should Panic Client thread "));	
+	
+	RThread testThread;
+	_LIT(KThreadName, "PanicClientThread");
+
+	testThread.Create(KThreadName, TestPanicThread, KDefaultStackSize, 0x1000, 0x100000, NULL);
+
+	TRequestStatus requestStatus;
+	// Request notification when the thread terminates
+	testThread.Logon(requestStatus);
+	
+	TBool justInTime=User::JustInTime(); 
+	User::SetJustInTime(EFalse); 
+	// Let the thread execute
+	testThread.Resume();
+
+	// Wait for termination
+	User::WaitForRequest(requestStatus);
+	User::SetJustInTime(justInTime); 
+
+	TEST2(testThread.ExitReason(), 0);
+	testThread.Close();
+
+	}
+
+static TInt RunTestsL()
+	{
+	TheTest.Next(_L("Delete old files"));
+	SchSvrHelpers::DeleteScheduleFilesL();
+	
+	//create P&S variables for the test
+	CreateTestVariables();
+	
+	TheTest.Next(_L("Start tests"));
+
+	CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+	CleanupStack::PushL(scheduler);
+	CActiveScheduler::Install(scheduler);
+	
+	DoTest1L();
+	DoTest2L();
+	DoTest3L();
+	DoTest4L();
+	DoTest5L();	
+	DoTest6L();
+	
+	TheTest.Next(_L("Tidying up"));
+	CleanupStack::PopAndDestroy(scheduler);
+
+	return KErrNone;
+	}
+
+GLDEF_C TInt E32Main()
+    {
+	__UHEAP_MARK;
+	TheTest.Start(_L("TC_TSCH_ROBUSTNESS"));
+	TheTest.Title();
+	TheCleanup = CTrapCleanup::New();
+
+	//If the previous test fails, SCHSVR.exe may stay in memory.
+	TRAPD(error,CleanupHelpers::TestCleanupL());
+	TEST2(error, KErrNone);
+	TheTest(TheFsSession.Connect() == KErrNone);;
+	TRAP(error, RunTestsL());
+	TEST2(error, KErrNone);	
+	TRAP(error,CleanupHelpers::TestCleanupL());
+	TEST2(error, KErrNone);
+	delete TheCleanup;	
+	
+	TheFsSession.Close();
+	TheTest.End();
+	TheTest.Close();
+	__UHEAP_MARKEND;
+
+	return KErrNone;
+	}