sl@0: // Copyright (c) 2004-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 "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: //
sl@0: 
sl@0: #include <csch_cli.h>
sl@0: #include "Thelpers.h"
sl@0: 
sl@0: #include <e32base.h>
sl@0: #include <e32test.h>
sl@0: #include <f32file.h>
sl@0: #include <s32file.h>
sl@0: 
sl@0: #include "TestUtils.h"
sl@0: 
sl@0: 
sl@0: //If suddenly all SCHSVR tests begin failing, the OOM conditions might be the reason.
sl@0: //TScheduling test tries to create KNumberOfSchedulesToCreate tasks, loading enormously 
sl@0: //the task scheduling server. The task scheduling server fails and stays loaded in memory
sl@0: //with many scheduling tasks holding large amounts of allocated memory in this way.
sl@0: //The next SCHSVR tests may fail because of OOM.
sl@0: //KNumberOfSchedulesToCreate value was 100 originally. Now it is 20.
sl@0: 
sl@0: //
sl@0: // Literal constants
sl@0: //
sl@0: _LIT(KTestName,								"TC_TSCH_SCHEDULING2");
sl@0: 
sl@0: //
sl@0: // Type definitions
sl@0: //
sl@0: typedef CArrayFixFlat<TScheduleEntryInfo>	CSchEntryInfoArray;
sl@0: typedef CArrayFixFlat<TTaskInfo>			CTaskInfoArray;
sl@0: typedef CArrayFixFlat<TSchedulerItemRef>    CSchItemRefArray;
sl@0: 
sl@0: //
sl@0: // Global data
sl@0: //
sl@0: RTest										TheTest(KTestName);
sl@0: static TInt64								TheSeed;
sl@0: static RScheduler							TheScheduler;
sl@0: static CTrapCleanup*						TheCleanup;
sl@0: static RFs									TheFsSession;
sl@0: 
sl@0: _LIT(KMinimalTaskHandler, "MinimalTaskHandler");
sl@0: 
sl@0: 
sl@0: //***********************************************************************************
sl@0: // Extract task info from the schedule server based on a schedule ID
sl@0: static void GetTaskInfoL(CTaskInfoArray& aTaskInfoArray,
sl@0: 						TInt aScheduleId)
sl@0: 	{
sl@0: 	aTaskInfoArray.Reset();
sl@0: 	TTime nextTimeScheduleIsDue;
sl@0: 	TScheduleState state;
sl@0: 	CSchEntryInfoArray* entries 
sl@0: 		= new (ELeave) CSchEntryInfoArray(3);
sl@0: 	CleanupStack::PushL(entries);
sl@0: 	TInt res = TheScheduler.GetScheduleL(aScheduleId, 
sl@0: 										state, 
sl@0: 										*entries, 
sl@0: 										aTaskInfoArray, 
sl@0: 										nextTimeScheduleIsDue);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	CleanupStack::PopAndDestroy(entries);
sl@0: 	}
sl@0: 
sl@0: // count the number of tasks associated with this schedule
sl@0: static TInt CountTasksL(TInt aScheduleId)	
sl@0: 	{
sl@0: 	CTaskInfoArray* tasks = new (ELeave) CTaskInfoArray(3);
sl@0: 	CleanupStack::PushL(tasks);
sl@0: 	GetTaskInfoL(*tasks, aScheduleId);
sl@0: 	TInt ret = tasks->Count();
sl@0: 	CleanupStack::PopAndDestroy(tasks);
sl@0: 	return ret;
sl@0: 	}
sl@0: 
sl@0: // count the number of schedules based on a filter.
sl@0: static TInt CountScheduledItemsL(TScheduleFilter aFilter, 
sl@0: 								RScheduler& aScheduler)
sl@0: 	{
sl@0: 	CSchItemRefArray* refs = new (ELeave) CSchItemRefArray(3);
sl@0: 	CleanupStack::PushL(refs);
sl@0: 
sl@0: 	TInt res = aScheduler.GetScheduleRefsL(*refs, aFilter);
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TInt count = refs->Count();
sl@0: 	CleanupStack::PopAndDestroy(); // refs
sl@0: 	return count;
sl@0: 	}
sl@0: 
sl@0: //creates a daily schedule with StartTime of aStartTime
sl@0: static TInt CreateScheduleL(TSchedulerItemRef& aRef, 
sl@0: 							RScheduler& aScheduler, 
sl@0: 							const TTime& aStartTime)
sl@0: 	{
sl@0: 	CSchEntryInfoArray* entryList 
sl@0: 		= new (ELeave) CSchEntryInfoArray(1);
sl@0: 	CleanupStack::PushL(entryList);
sl@0: 
sl@0: 	TScheduleEntryInfo entry1;
sl@0: 	entry1.iStartTime		= aStartTime;
sl@0: 	entry1.iInterval		= 1; // TTimeIntervalDays
sl@0: 	entry1.iIntervalType	= EDaily;
sl@0: 	entry1.iValidityPeriod	= 30; // minutes
sl@0: 	entryList->AppendL(entry1);
sl@0: 	TInt res = aScheduler.CreatePersistentSchedule(aRef, *entryList);
sl@0: 	CleanupStack::PopAndDestroy(); // entryList
sl@0: 	return res;
sl@0: 	}
sl@0: 	
sl@0: // creates a schedule with numerous entries	
sl@0: static TInt CreateSchedule1L(TSchedulerItemRef& aRef, RScheduler& aScheduler)
sl@0: 	{
sl@0: 	aRef.iName = _L("Schedule created using \"CreateSchedule1L\"");
sl@0: 
sl@0: 	CSchEntryInfoArray* entryList = new (ELeave) CSchEntryInfoArray(3);
sl@0: 	CleanupStack::PushL(entryList);
sl@0: 
sl@0: 	{
sl@0: 	TScheduleEntryInfo entry1;
sl@0: 	entry1.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(20, 0); // 0m:20s from "now"
sl@0: 	entry1.iInterval		= 1;
sl@0: 	entry1.iIntervalType	= EDaily;
sl@0: 	entry1.iValidityPeriod	= 20;
sl@0: 	entryList->AppendL(entry1);
sl@0: 	}
sl@0: 	{
sl@0: 	TScheduleEntryInfo entry2;
sl@0: 	entry2.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(00, 1); // 1m:00s from "now"
sl@0: 	entry2.iInterval		= 1;
sl@0: 	entry2.iIntervalType	= EDaily;
sl@0: 	entry2.iValidityPeriod	= 20;
sl@0: 	entryList->AppendL(entry2);
sl@0: 	}
sl@0: 	{
sl@0: 	TScheduleEntryInfo entry3;
sl@0: 	entry3.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(0, 0, 0, 0, 0, -1); // -1 year from "now"
sl@0: 	entry3.iInterval		= 1;
sl@0: 	entry3.iIntervalType	= EDaily;
sl@0: 	entry3.iValidityPeriod	= 20;
sl@0: 	entryList->AppendL(entry3);
sl@0: 	}
sl@0: 
sl@0: 	TInt res = aScheduler.CreatePersistentSchedule(aRef, *entryList);
sl@0: 	CleanupStack::PopAndDestroy(); // entryList
sl@0: 	return res;
sl@0: 	}
sl@0: 
sl@0: // creates a schedule with numerous entries	
sl@0: static TInt CreateSchedule2L(TSchedulerItemRef& aRef, RScheduler& aScheduler)
sl@0: 	{
sl@0: 	CSchEntryInfoArray* entryList = new (ELeave) CSchEntryInfoArray(3);
sl@0: 	CleanupStack::PushL(entryList);
sl@0: 
sl@0: 	aRef.iName = _L("Schedule created using \"CreateSchedule2L\"");
sl@0: 
sl@0: 	{
sl@0: 	TScheduleEntryInfo entry1;
sl@0: 	entry1.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(30, 2); // 2m:30s from "now"
sl@0: 	entry1.iInterval		= 1;
sl@0: 	entry1.iIntervalType	= EDaily;
sl@0: 	entry1.iValidityPeriod	= 20;
sl@0: 	entryList->AppendL(entry1);
sl@0: 	}
sl@0: 	{
sl@0: 	TScheduleEntryInfo entry2;
sl@0: 	entry2.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(0, 5);  // 5m:00s from "now"
sl@0: 	entry2.iInterval		= 1;
sl@0: 	entry2.iIntervalType	= EDaily;
sl@0: 	entry2.iValidityPeriod	= 20;
sl@0: 	entryList->AppendL(entry2);
sl@0: 	}
sl@0: 
sl@0: 	TInt res = aScheduler.CreatePersistentSchedule(aRef, *entryList);
sl@0: 	CleanupStack::PopAndDestroy(); // entryList
sl@0: 	return res;
sl@0: 	}
sl@0: 
sl@0: // creates a schedule with numerous entries	
sl@0: static TInt CreateSchedule3L(TSchedulerItemRef& aRef, RScheduler& aScheduler)
sl@0: 	{
sl@0: 	CSchEntryInfoArray* entryList = new (ELeave) CSchEntryInfoArray(3);
sl@0: 	CleanupStack::PushL(entryList);
sl@0: 
sl@0: 	aRef.iName = _L("Schedule created using \"CreateSchedule3L\"");
sl@0: 
sl@0: 	{
sl@0: 	TScheduleEntryInfo entry1;
sl@0: 	entry1.iIntervalType	= EDaily;
sl@0: 	entry1.iInterval		= 1; // repeat every day
sl@0: 	entry1.iValidityPeriod	= 5; // valid for only 5 minutes 
sl@0: 	entry1.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(0, 9, 0, 20); // 9mins and 20days in the future
sl@0: 	entryList->AppendL(entry1);
sl@0: 	}
sl@0: 	
sl@0: 	{
sl@0: 	TScheduleEntryInfo entry2;
sl@0: 	entry2.iIntervalType	= EDaily;
sl@0: 	entry2.iInterval		= 1;
sl@0: 	entry2.iValidityPeriod	= 5;
sl@0: 	entry2.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(0, 11, 0, 20); // 11mins and 20days in the future
sl@0: 	entryList->AppendL(entry2);
sl@0: 	}
sl@0: 
sl@0: 	TInt res = aScheduler.CreatePersistentSchedule(aRef, *entryList);
sl@0: 	CleanupStack::PopAndDestroy(); // entryList
sl@0: 
sl@0: 	return res;
sl@0: 	}
sl@0: 
sl@0: // schedules a persistent task associated with the supplied schedule ID
sl@0: static TInt SchedulePersistentTaskL(const TName& aName, 
sl@0: 									TInt& aNewId, 
sl@0: 									TInt aScheduleId, 
sl@0: 									TInt aRepeat, 
sl@0: 									RScheduler& aScheduler)
sl@0: 	{
sl@0: 	TTaskInfo taskInfo;
sl@0: 	taskInfo.iTaskId = aNewId;
sl@0: 	taskInfo.iName = aName;
sl@0: 	taskInfo.iPriority = 2;
sl@0: 	taskInfo.iRepeat = aRepeat;
sl@0: 	HBufC* data = _L("the data").AllocLC();
sl@0: 	TInt res = aScheduler.ScheduleTask(taskInfo, *data, aScheduleId);
sl@0: 	aNewId = taskInfo.iTaskId;
sl@0: 
sl@0: 	CleanupStack::PopAndDestroy(); // data
sl@0: 	return res;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1033
sl@0: @SYMTestCaseDesc	    Test 1 - verifies fix for defect:
sl@0: 						Registering twice with the task scheduler causes a memory leak(EDNAWIR-4FQJ6A)
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Connect to scheduler and register twice with the task scheduler.Check for memory errors,
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void Test1L()
sl@0: 	{
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1033 TheTest1: Registering with the tasks scheduler without disconnecting "));    
sl@0: 	__UHEAP_MARK;
sl@0: 	TheTest.Next(_L("Connect to Scheduler"));
sl@0: 	TInt res = TheScheduler.Connect();
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Registering Client"));
sl@0: 	TEST2(SchSvrHelpers::RegisterClientL(TheScheduler), KErrNone);
sl@0: 
sl@0: 	TheScheduler.Close();
sl@0: 	__UHEAP_MARKEND;
sl@0: 
sl@0: 	__UHEAP_MARK;
sl@0: 	TheTest.Next(_L("Connect to Scheduler again"));
sl@0: 	res = TheScheduler.Connect();
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Registering client again"));
sl@0: 	TEST2(SchSvrHelpers::RegisterClientL(TheScheduler), KErrNone);
sl@0: 	TheScheduler.__DbgMarkHeap();
sl@0: 
sl@0: 	TheTest.Next(_L("Register when already registered"));
sl@0: 	TEST2(SchSvrHelpers::RegisterClientL(TheScheduler), KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Cancel registering client and check for memory leak"));
sl@0: 	TheScheduler.__DbgMarkEnd(0);
sl@0: 	TheScheduler.Close();
sl@0: 	__UHEAP_MARKEND;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1034
sl@0: @SYMTestCaseDesc	    Test 2 - verifies fix for defect
sl@0: 						Messages with "Resend" status are not sent after reboot (EDNHLJT-4TRAAE)
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Add a task to the schedule,kill the server and re-register the client,wait for one minute for task to fire
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void Test2L()
sl@0: //
sl@0: //
sl@0: 	{
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1034 TheTest2: Resend after hard reset (simulation) "));
sl@0: 
sl@0: 	TheTest.Next(_L("Connect to Scheduler"));
sl@0: 	TInt res = TheScheduler.Connect();
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Registering Client"));
sl@0: 	TEST2(SchSvrHelpers::RegisterClientL(TheScheduler), KErrNone);
sl@0: 
sl@0: 	// Create a schedule
sl@0: 	TheTest.Next(_L("Creating schedule"));
sl@0: 	TSchedulerItemRef scheduleHandle;
sl@0: 	TTime time;
sl@0: 	time.HomeTime();
sl@0: 	time += TTimeIntervalSeconds(2); //Task to go off two seconds from now
sl@0: 	User::LeaveIfError(CreateScheduleL(scheduleHandle, TheScheduler, time));  
sl@0: 
sl@0: 	// Add a task to the schedule
sl@0: 	TheTest.Next(_L("Creating task for schedule"));
sl@0: 	{
sl@0: 	TTaskInfo taskInfo;
sl@0: 	taskInfo.iName = _L("MyTaskName");
sl@0: 	taskInfo.iPriority = 2;
sl@0: 	taskInfo.iTaskId = 0;
sl@0: 	taskInfo.iRepeat = 1;
sl@0: 	HBufC* data = _L("Task Data").AllocLC();
sl@0: 	TInt res = TheScheduler.ScheduleTask(taskInfo, *data, scheduleHandle.iHandle);
sl@0: 	CleanupStack::PopAndDestroy(); // data
sl@0: 	TEST2(res, KErrNone);
sl@0: 	}
sl@0: 
sl@0: 	// Kill the server !!
sl@0: 	TheTest.Next(_L("Killing server"));
sl@0: 	// Need to turn off JIT dubugging as we are panicking server and we 
sl@0: 	// want test to keep running.
sl@0: 	TBool jit = User::JustInTime();
sl@0: 	User::SetJustInTime(EFalse);
sl@0: 
sl@0: 	TheScheduler.__FaultServer();
sl@0: 	User::After(100000);
sl@0: 	
sl@0: 	// Turn on JIT again.
sl@0: 	User::SetJustInTime(jit);
sl@0: 	
sl@0: 	// Connect to the server again
sl@0: 	TheTest.Next(_L("Re-connect to Scheduler"));
sl@0: 	res = TheScheduler.Connect();
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	// Re-register
sl@0: 	TheTest.Next(_L("Re-register Client"));
sl@0: 	TEST2(SchSvrHelpers::RegisterClientL(TheScheduler), KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Check schedule count and task count"));
sl@0: 	TInt scheduleCount = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	TEST(scheduleCount == 1);
sl@0: 	TInt taskCount = CountTasksL(scheduleHandle.iHandle);
sl@0: 	TEST(taskCount == 1);
sl@0: 	
sl@0: 	// Wait for task to fire... It should happen in about 2 seconds
sl@0: 	TheTest.Next(_L("Waiting for task to complete"));
sl@0: 	TEST2(STaskSemaphore::WaitL(KDefaultTimeout), KErrNone);
sl@0: 	CleanupHelpers::KillProcess(KMinimalTaskHandler);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1035
sl@0: @SYMTestCaseDesc	    This test establishes that the change to RScheduler::GetScheduleL is functionally correct
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests changes to Schedule Server API as of Change Request document AALR-4EDG75
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void Test3L()
sl@0: 	{
sl@0: 	//
sl@0: 	//
sl@0: 	// Test changes to Schedule Server API as of Change Request document AALR-4EDG75
sl@0: 	// (GT change requests database)
sl@0: 	//
sl@0: 	//
sl@0: 	//
sl@0: 	// This test establishes that the change to...
sl@0: 	//
sl@0: 	//	RScheduler::GetScheduleL(const TInt aScheduleHandle,
sl@0: 	//								 TScheduleState& aState,
sl@0: 	//								 CArrayFixFlat<TScheduleEntryInfo>& aEntries,
sl@0: 	//								 CArrayFixFlat<TTaskInfo>& aTasks,
sl@0: 	//								 TTime& aNextDue)
sl@0: 	//
sl@0: 	// ...is functionally correct.
sl@0: 	// 
sl@0: 	//
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1035 Test change request AALR-4EDG75 implementation "));
sl@0: 	
sl@0: 	TheTest.Next(_L("Connect to Scheduler"));
sl@0: 	TInt res = TheScheduler.Connect();
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Registering Client"));
sl@0: 	TEST2(SchSvrHelpers::RegisterClientL(TheScheduler), KErrNone);
sl@0: 
sl@0: 	const TDateTime KTimeToStartTask(2000, EJanuary, 10, 15, 30, 0, 0);
sl@0: 
sl@0: 	TSchedulerItemRef schedulerItemReference;
sl@0: 	CSchEntryInfoArray* entryArray = new(ELeave) CSchEntryInfoArray(1);
sl@0: 	CleanupStack::PushL(entryArray);
sl@0: 	
sl@0: 	HBufC* taskData = _L("This is some dummy task data created for testing").AllocL();
sl@0: 	CleanupStack::PushL(taskData);
sl@0: 	
sl@0: 	// Prepare the task info - this describes the tasks that are contained within the task
sl@0: 	// entry array
sl@0: 	TTaskInfo taskInfo = SchSvrHelpers::TaskInfo(_L("A transient test task"), 100);
sl@0: 		
sl@0: 	// Create a schedule entry and append it to the entry array
sl@0: 	{
sl@0: 	TScheduleEntryInfo scheduleEntry = SchSvrHelpers::ScheduleEntryInfo(EDaily, TTime(KTimeToStartTask), 7, 2);
sl@0: 	entryArray->AppendL(scheduleEntry);
sl@0: 	}
sl@0: 
sl@0: 	// Create the transient task
sl@0: 	TInt ret = TheScheduler.ScheduleTask(taskInfo, *taskData, schedulerItemReference, *entryArray);
sl@0: 	TEST2(ret, KErrNone);
sl@0: 
sl@0: 	// Check that the task Id after scheduling the event is not 
sl@0: 	// the same as it was prior to the requesting the service
sl@0: 	TEST(taskInfo.iTaskId != -1);
sl@0: 
sl@0: 	//
sl@0: 	// Now obtain info about the scheduled transient task...
sl@0: 	//
sl@0: 	TScheduleState scheduleState;
sl@0: 	TTime nextTaskDueTime;
sl@0: 
sl@0: 	// Reset the schedule entry info array as the server now has copies of this and it is
sl@0: 	// no longer required client-side
sl@0: 	entryArray->Reset();
sl@0: 	CTaskInfoArray* taskInfoArray = new(ELeave) CTaskInfoArray(4);
sl@0: 	CleanupStack::PushL(taskInfoArray);
sl@0: 
sl@0: 	// Request task schedule information from the server
sl@0: 	ret = TheScheduler.GetScheduleL(schedulerItemReference.iHandle, scheduleState, *entryArray, *taskInfoArray, nextTaskDueTime);
sl@0: 	TEST2(ret, KErrNone);
sl@0: 
sl@0: 	// Because this is a daily task which is scheduled to occur at a specific time (but the date
sl@0: 	// cannot necessarily be established, we can perform a simple check to ensure that the
sl@0: 	// time when the task is next scheduled to run falls within the 15:30 - 17:30 bracket.
sl@0: 	TEST(SchSvrHelpers::IsTimeTheSame(nextTaskDueTime, TTime(KTimeToStartTask)) == (TInt) ETrue);
sl@0: 
sl@0: 	// Establish and test the size of the task data for the specified task object
sl@0: 	TInt sizeOfTaskData = 0;
sl@0: 	TEST2(TheScheduler.GetTaskDataSize(taskInfo.iTaskId, sizeOfTaskData), KErrNone);
sl@0: 	TEST(sizeOfTaskData == taskData->Length());
sl@0: 
sl@0: 	// Now check the information return from the server pertaining to a specific task...
sl@0: 	{
sl@0: 	TTaskInfo taskFromServer;
sl@0: 	HBufC* taskDataFromServer					= HBufC::NewLC(sizeOfTaskData);
sl@0: 	TPtr pTaskDataFromServer					= taskDataFromServer->Des();
sl@0: 	TTime nextDueTimeFromServer					= Time::NullTTime();
sl@0: 	TSchedulerItemRef schedulerRefFromServer;
sl@0: 	TEST2(TheScheduler.GetTaskInfoL(taskInfo.iTaskId, taskFromServer, pTaskDataFromServer, schedulerRefFromServer, nextDueTimeFromServer), KErrNone);
sl@0: 	TEST(SchSvrHelpers::IsTimeTheSame(nextTaskDueTime, TTime(KTimeToStartTask)) == (TInt) ETrue);
sl@0: 	TEST(SchSvrHelpers::IsTaskInfoTheSame(taskFromServer, taskInfo) == (TInt) ETrue);
sl@0: 	TEST(SchSvrHelpers::IsItemRefTheSame(schedulerRefFromServer, schedulerItemReference) == (TInt) ETrue);
sl@0: 	CleanupStack::PopAndDestroy(); // taskDataFromServer
sl@0: 	}
sl@0: 
sl@0: 	// Disable the schedule and check when it is next schedule to run
sl@0: 	TEST2(TheScheduler.DisableSchedule(schedulerItemReference.iHandle), KErrNone);
sl@0: 
sl@0: 	// Get the new schedule info - check that the nextDueTime is still reported even
sl@0: 	// though the schedule has been disabled
sl@0: 	nextTaskDueTime = Time::NullTTime();
sl@0: 	TEST2(TheScheduler.GetScheduleL(schedulerItemReference.iHandle, scheduleState, *entryArray, *taskInfoArray, nextTaskDueTime), KErrNone);
sl@0: 	TEST(SchSvrHelpers::IsTimeTheSame(nextTaskDueTime, TTime(KTimeToStartTask)) == (TInt) ETrue);
sl@0: 	TEST(SchSvrHelpers::IsTaskInfoTheSame(taskInfoArray->At(0), taskInfo) == (TInt) ETrue);
sl@0: 
sl@0: 	// Re-enable the schedule
sl@0: 	TEST2(TheScheduler.EnableSchedule(schedulerItemReference.iHandle), KErrNone);
sl@0: 
sl@0: 	// Delete the only task (relating to this test) from the server
sl@0: 	TEST2(TheScheduler.DeleteTask(taskInfo.iTaskId), KErrNone);
sl@0: 	ret = TheScheduler.GetScheduleL(schedulerItemReference.iHandle, scheduleState, *entryArray, *taskInfoArray, nextTaskDueTime);
sl@0: 	TEST2(ret, KErrNotFound); // there is no longer any tasks associated with this schedule
sl@0: 
sl@0: 	CleanupStack::PopAndDestroy(3); // taskInfoArray, entryArray, taskData
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1036
sl@0: @SYMTestCaseDesc	    Tests for defect EDNAALR-4JKEFC
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Create the schedule for the task,re-register the client with the server.
sl@0:                         check for the information that the scheduler knows about.
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void Test4L()
sl@0: 	{
sl@0: 	// Test title
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1036 \nTest for defect EDNAALR-4JKEFC "));
sl@0: 	
sl@0: 	TheTest.Next(_L("Connect to Scheduler"));
sl@0: 	TInt res = TheScheduler.Connect();
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Registering Client"));
sl@0: 	TEST2(SchSvrHelpers::RegisterClientL(TheScheduler), KErrNone);
sl@0: 
sl@0: 	// Constants / vars used in this function
sl@0: 	TSchedulerItemRef itemRef;
sl@0: 
sl@0: 	// Create some scheduling entries
sl@0: 	CArrayFixFlat<TScheduleEntryInfo>* entries = new(ELeave) CArrayFixFlat<TScheduleEntryInfo>(10);
sl@0: 	CleanupStack::PushL(entries);
sl@0: 
sl@0: 	TScheduleEntryInfo entry1;
sl@0: 	entry1.iIntervalType	= EHourly;
sl@0: 	entry1.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(1, 1); // 1m:01s from "now"
sl@0: 	entry1.iInterval		= 1;
sl@0: 	entry1.iValidityPeriod	= 20;
sl@0: 	entries->AppendL(entry1);
sl@0: 
sl@0: 	TScheduleEntryInfo entry2;
sl@0: 	entry2.iIntervalType	= EHourly;
sl@0: 	entry2.iStartTime		= SchSvrHelpers::TimeBasedOnOffset(5, 5); // 5m:05s from "now"
sl@0: 	entry2.iInterval		= 1;
sl@0: 	entry2.iValidityPeriod	= 20;
sl@0: 	entries->AppendL(entry2);
sl@0: 
sl@0: 	// Create the schedule for the task...
sl@0: 	res = TheScheduler.CreatePersistentSchedule(itemRef, *entries);
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	// Create the tasks themselves..
sl@0: 	TTaskInfo task;
sl@0: 	task.iRepeat	= 10; // repeat once
sl@0: 	task.iName		= _L("Test Task For Defect Verification");
sl@0: 	task.iPriority	= 100;
sl@0: 	HBufC* taskData = task.iName.AllocLC();
sl@0: 	res = TheScheduler.ScheduleTask(task, *taskData, itemRef.iHandle);
sl@0: 	CleanupStack::PopAndDestroy(); // taskData
sl@0: 
sl@0: 	{
sl@0: 	CArrayFixFlat<TSchedulerItemRef>* refs = new CArrayFixFlat<TSchedulerItemRef>(3);
sl@0: 	CleanupStack::PushL(refs);
sl@0: 	TInt res = TheScheduler.GetScheduleRefsL(*refs, EAllSchedules); 
sl@0: 	TEST2(res, KErrNone);
sl@0: 	CleanupStack::PopAndDestroy(); // refs
sl@0: 	}
sl@0: 
sl@0: 	// Re-register theclient with the server
sl@0: 	for(TInt i=0; i<5; i++)
sl@0: 		{
sl@0: 		// Log off from the task scheduler
sl@0: 		TheScheduler.Close();
sl@0: 		res = TheScheduler.Connect();
sl@0: 		TEST2(res, KErrNone);
sl@0: 
sl@0: 		User::After(1000000); 
sl@0: 
sl@0: 		TheTest.Next(_L("===== Re-registering Client (wait 10 secs) ====="));
sl@0: 		res = SchSvrHelpers::RegisterClientL(TheScheduler);
sl@0: 		TEST2(res, KErrNone);
sl@0: 			{
sl@0: 			CArrayFixFlat<TSchedulerItemRef>* refs = new CArrayFixFlat<TSchedulerItemRef>(3);
sl@0: 			CleanupStack::PushL(refs);
sl@0: 			TInt res = TheScheduler.GetScheduleRefsL(*refs, EAllSchedules);
sl@0: 			TEST2(res, 0);
sl@0: 			CleanupStack::PopAndDestroy(); // refs
sl@0: 			}
sl@0: 
sl@0: 		// Check the information that the scheduler knows about...
sl@0: 		TInt taskDataSize = 0;
sl@0: 		res = TheScheduler.GetTaskDataSize(task.iTaskId, taskDataSize);
sl@0: 		TEST2(res, KErrNone);
sl@0: 		TEST(taskDataSize == task.iName.Length());
sl@0: 		TTaskInfo taskInfoFromServer;
sl@0: 		taskData = HBufC::NewLC(taskDataSize);
sl@0: 		TPtr pTaskData = taskData->Des();
sl@0: 
sl@0: 		TTime nextDueTime(Time::NullTTime());
sl@0: 		res = TheScheduler.GetTaskInfoL(task.iTaskId, taskInfoFromServer, pTaskData, itemRef, nextDueTime);
sl@0: 		TEST2(res, KErrNone);
sl@0: 		TEST(pTaskData == task.iName);
sl@0: 		CleanupStack::PopAndDestroy(); // taskData
sl@0: 		}
sl@0: 
sl@0: 	CleanupStack::PopAndDestroy(); // entries
sl@0: 
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1037
sl@0: @SYMTestCaseDesc	    Tests for basic scheduler implementations 
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Mark heap,create persistent schedules, schedule tasks,transient schedules,
sl@0:                         delete tasks,delete remaing schedules,check heap
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void Test5L()
sl@0: 	{
sl@0: 	TInt res = KErrNone;
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1037 ===== Starting test 1 ====="));
sl@0: 	__UHEAP_MARK;
sl@0: 	
sl@0: 	TSchedulerItemRef ref1;
sl@0: 	TSchedulerItemRef ref2;
sl@0: 	TSchedulerItemRef ref3;
sl@0: 
sl@0: 	// Remove all existing schedules before starting the test
sl@0: 	SchSvrHelpers::DeleteAllSchedulesL(TheScheduler);
sl@0: 	
sl@0: 	TInt scheduleCount = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	TEST(scheduleCount == 0); // check that no schedules are present.
sl@0: 	
sl@0: 	TheTest.Printf(_L("Create some schedules\n"));
sl@0: 	res = CreateSchedule1L(ref1, TheScheduler); // +20sec, +1min, -1year
sl@0: 	TEST2(res, KErrNone);	
sl@0: 	res = CreateSchedule2L(ref2, TheScheduler); // +2min 30sec, +5min
sl@0: 	TEST2(res, KErrNone);
sl@0: 	res = CreateSchedule3L(ref3, TheScheduler); // +20day 9min, +20day 11min
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TSchedulerItemRef ref4;
sl@0: 	TSchedulerItemRef ref5;
sl@0: 	res = CreateSchedule2L(ref4, TheScheduler); // +2min 30sec, 5min
sl@0: 	TEST2(res, KErrNone);
sl@0: 	res = CreateSchedule3L(ref5, TheScheduler); // +20day 9min, +20day 11min
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TInt task1 = 0;
sl@0: 	TInt task2 = 0;
sl@0: 	TInt task3 = 0;
sl@0: 	TInt task4 = 0;
sl@0: 	TName name1 = (_L("web subscription"));
sl@0: 	TName name2 = (_L("another web subscription"));
sl@0: 	TName name3 = (_L("third web subscription"));
sl@0: 
sl@0: 	TheTest.Printf(_L("Schedule some tasks\n"));
sl@0: 
sl@0: 	// NOTE: have to put repeats here of > 0 otherwise the task will run immediately
sl@0: 	// (because it's schedule specifies a date of 1 year in the past!) and be
sl@0: 	// removed (by the server) before we have a chance to delete it....
sl@0: 	res = SchedulePersistentTaskL(name1, task1, ref1.iHandle, 3, TheScheduler);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	res = SchedulePersistentTaskL(name2, task2, ref2.iHandle, 3, TheScheduler);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	res = SchedulePersistentTaskL(name3, task3, ref3.iHandle, 3, TheScheduler);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	res = SchedulePersistentTaskL(name3, task4, ref3.iHandle, 3, TheScheduler);
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	scheduleCount = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	TEST(scheduleCount == 5); // 5 persistant
sl@0: 	CleanupHelpers::KillProcess(KMinimalTaskHandler);
sl@0: 
sl@0: 	TheTest.Printf(_L("Deleting task with id %d\n"), task1);
sl@0: 	res = TheScheduler.DeleteTask(task1);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	TheTest.Printf(_L("Deleting schedule with id %d\n"), ref1.iHandle);
sl@0: 	res = TheScheduler.DeleteSchedule(ref1.iHandle);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	scheduleCount = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	// 4 persistant expected as we have deleted one
sl@0: 	TEST(scheduleCount == 4); 
sl@0: 
sl@0: 	TheTest.Printf(_L("Deleting task with id %d\n"), task2);
sl@0: 	res = TheScheduler.DeleteTask(task2);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	TheTest.Printf(_L("Deleting schedule with id %d\n"), ref2.iHandle);
sl@0: 	res = TheScheduler.DeleteSchedule(ref2.iHandle);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	scheduleCount = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	// 3 persistant  expected as we have deleted one
sl@0: 	TEST(scheduleCount == 3); 
sl@0: 
sl@0: 	TheTest.Printf(_L("Deleting task with id %d\n"), task3);
sl@0: 	res = TheScheduler.DeleteTask(task3);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	TheTest.Printf(_L("Deleting task with id %d\n"), task4);
sl@0: 	res = TheScheduler.DeleteTask(task4);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	TheTest.Printf(_L("Deleting schedule with id %d\n"), ref3.iHandle);
sl@0: 	res = TheScheduler.DeleteSchedule(ref3.iHandle);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	scheduleCount = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	// 2 persistant  expected as we have deleted one
sl@0: 	TEST(scheduleCount == 2); 
sl@0: 
sl@0: 	TheTest.Printf(_L("Deleting schedule with id %d\n"), ref4.iHandle);
sl@0: 	res = TheScheduler.DeleteSchedule(ref4.iHandle);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	TheTest.Printf(_L("Deleting schedule with id %d\n"), ref5.iHandle);
sl@0: 	res = TheScheduler.DeleteSchedule(ref5.iHandle);
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	scheduleCount = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	TEST(scheduleCount == 0); 
sl@0: 	
sl@0: 	SchSvrHelpers::Pause(TheTest);
sl@0: 	__UHEAP_MARKEND;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1038
sl@0: @SYMTestCaseDesc	    Tests for Transient,non-repeating - waits for schedule to activate
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Create transient schedule with non-repeating task
sl@0:                         Tests for no items as schedule deletes itself after task has completed
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void Test6L()
sl@0: 	{
sl@0: 	// Heap testing removed because this is a flakey bit of code.
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1038 Transient, non-repeating - waits for schedule to activate "));
sl@0: 	
sl@0: 	// Remove all existing schedules before starting the test
sl@0: 	SchSvrHelpers::DeleteAllSchedulesL(TheScheduler);
sl@0: 
sl@0: 	// Create transient schedule
sl@0: 	TheTest.Printf(_L("Create transient schedule with non-repeating task\n"));
sl@0: 	TSchedulerItemRef ref;
sl@0: 	CSchEntryInfoArray* entryList = new(ELeave) CSchEntryInfoArray(1);
sl@0: 	CleanupStack::PushL(entryList);
sl@0: 	ref.iName = _L("A Transient Schedule");
sl@0: 
sl@0: 	// Create schedule entry
sl@0: 	TScheduleEntryInfo entry;
sl@0: 	entry.iStartTime = SchSvrHelpers::TimeBasedOnOffset(5); // 5 secs in the future
sl@0: 	entry.iInterval = 1;
sl@0: 	entry.iIntervalType = EDaily;
sl@0: 	entry.iValidityPeriod = 20;
sl@0: 	entryList->AppendL(entry);
sl@0: 	
sl@0: 	// Create schedule task
sl@0: 	TTaskInfo taskInfo;
sl@0: 	taskInfo.iName = _L("mail");
sl@0: 	taskInfo.iTaskId = 0;
sl@0: 	taskInfo.iRepeat = 1;
sl@0: 	taskInfo.iPriority = 2;
sl@0: 	HBufC* data = _L("This is the data for the task").AllocLC();
sl@0: 
sl@0: 	// Schedule the item
sl@0: 	TInt res = TheScheduler.ScheduleTask(taskInfo, *data, ref, *entryList);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	CleanupStack::PopAndDestroy(2, entryList); // data, entryList
sl@0: 
sl@0: 	// Should be one item
sl@0: 	TEST(CountScheduledItemsL(EAllSchedules, TheScheduler) == 1);
sl@0: 
sl@0: 	// Waiting for entry to complete
sl@0: 	TheTest.Next(_L("Waiting for task to complete"));
sl@0: 	TEST2(STaskSemaphore::WaitL(KDefaultTimeout), KErrNone);
sl@0: 	CleanupHelpers::KillProcess(KMinimalTaskHandler);
sl@0: 	// Should be no items as schedule deletes itself after task has completed
sl@0: 	TEST(CountScheduledItemsL(EAllSchedules, TheScheduler) == 0);
sl@0: 
sl@0: 	SchSvrHelpers::Pause(TheTest);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1039
sl@0: @SYMTestCaseDesc	    Tests for persistent scheduling, repeating and non-repeating task schedules
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Persistent schedule,repeating task,non-repeating task,go off,check task's still there,
sl@0: 						go off again,check it's still there,delete task,delete schedule
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void Test7L()
sl@0: 	{
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1039 Test persistent scheduling, repeating and non-repeating task schedules "));
sl@0: 	SchSvrHelpers::DeleteAllSchedulesL(TheScheduler);
sl@0: 
sl@0: 	// Transient
sl@0: 	TSchedulerItemRef ref;
sl@0: 
sl@0: 	// We shouldn't have any outstanding schedules registered with the server
sl@0: 	TInt count = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	TEST(count == 0);
sl@0: 
sl@0: 	// This creates 3 schedule entries, each with a validity period of 20 minutes, and are
sl@0: 	// due to run in 20s, 1m, and over a year ago (a year in the past)
sl@0: 	TheTest.Printf(_L("Create Persistent schedule\n"));
sl@0: 	TInt res = CreateSchedule1L(ref, TheScheduler);
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	// We should now have one registered schedule
sl@0: 	count = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	TEST(count == 1);
sl@0: 
sl@0: 	//
sl@0: 	TheTest.Printf(_L("\nSchedule two tasks: one repeating....\n"));
sl@0: 	//
sl@0: 	TInt task1 = 0;
sl@0: 	TName name1 = (_L("web subscription(rpts)"));
sl@0: 	// -1 indicates repeating schedule
sl@0: 	res = SchedulePersistentTaskL(name1, task1, ref.iHandle, -1, TheScheduler); // -1 indicates repeat until explicitly deleted
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	// List those schedules that are pending
sl@0: 	count = CountScheduledItemsL(EPendingSchedules, TheScheduler);
sl@0: 	TEST(count == 1);
sl@0: 
sl@0: 	//
sl@0: 	TheTest.Printf(_L("\n... and one non-repeating\n"));
sl@0: 	//
sl@0: 	TInt task2 = 0;
sl@0: 	TName name2 = (_L("non-repeating"));
sl@0: 	res = SchedulePersistentTaskL(name2, task2, ref.iHandle, 1, TheScheduler); // only runs once
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TheTest.Printf(_L("Waiting for tasks to run\n"));
sl@0: 	// Wait for notification that schedule has executed.
sl@0: 	TEST2(STaskSemaphore::WaitL(KDefaultTimeout), KErrNone);
sl@0: 	CleanupHelpers::KillProcess(KMinimalTaskHandler);
sl@0: 
sl@0: 	TheTest.Printf(_L("...and wait again for repeating one to execute again\n"));
sl@0: 	// Wait for notification that schedule has executed.
sl@0: 	TEST2(STaskSemaphore::WaitL(KDefaultTimeout), KErrNone);
sl@0: 	CleanupHelpers::KillProcess(KMinimalTaskHandler);
sl@0: 
sl@0: 	TheTest.Printf(_L("Delete the repeating task, and the schedule \n"));
sl@0: 	res = TheScheduler.DeleteTask(task1);
sl@0: 	TEST2(res, KErrNone);
sl@0: 	res = TheScheduler.DeleteTask(task2);
sl@0: 	TEST2(res, KErrNotFound); //Should be not found since its only executed once.
sl@0: 	res = TheScheduler.DeleteSchedule(ref.iHandle);
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	count = CountScheduledItemsL(EPendingSchedules, TheScheduler);
sl@0: 	TEST(count == 0);
sl@0: 	SchSvrHelpers::Pause(TheTest);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: static CSchEntryInfoArray* CreateSchEntryInfoArrayLC(TInt aGranularity)
sl@0: 	{
sl@0: 	CSchEntryInfoArray*	scheduleEntries	= new (ELeave) CSchEntryInfoArray(aGranularity);
sl@0: 	CleanupStack::PushL(scheduleEntries);
sl@0: 	return scheduleEntries;
sl@0: 	}
sl@0: 
sl@0: static CArrayFixFlat<TTaskInfo>* CreateTaskInfoLC(TInt aGranularity)
sl@0: 	{
sl@0: 	CArrayFixFlat<TTaskInfo>* taskInfos	= new (ELeave) CArrayFixFlat<TTaskInfo>(aGranularity);
sl@0: 	CleanupStack::PushL(taskInfos);
sl@0: 	return taskInfos;
sl@0: 	}
sl@0: 
sl@0: static CSchItemRefArray* CreateScheduleRefsLC(TInt aGranularity)
sl@0: 	{
sl@0: 	CSchItemRefArray* scheduleReferences = new (ELeave) CSchItemRefArray(aGranularity);
sl@0: 	CleanupStack::PushL(scheduleReferences);
sl@0: 	return scheduleReferences;
sl@0: 	}
sl@0: 
sl@0: static void CreateTransientScheduledTasksL(TInt aNumScheduleEntries,
sl@0: 										   TInt aNumSchedules,
sl@0: 										   CSchEntryInfoArray* aScheduleEntries,
sl@0: 										   CArrayFixFlat<TTaskInfo>* aTaskInfos,
sl@0: 										   CSchItemRefArray* aScheduleReferences)
sl@0: 	{
sl@0: 	const TTimeIntervalMicroSeconds timeToAdd = 10000000; //10 seconds
sl@0: 	const TTimeIntervalMicroSeconds timeLimit = 5000000; // 5 seconds
sl@0: 	_LIT(KTaskDataPrefix, "Task Data Entry: ");
sl@0: 	// Prepare keys required
sl@0: 	TKeyArrayFix KTaskInfoSortKey(_FOFF(TTaskInfo, iTaskId), ECmpTInt);
sl@0: 
sl@0: 	for(TInt i=0;i<aNumSchedules;i++)
sl@0: 		{	
sl@0: 		// Remove any existing schedule entry info's
sl@0: 		aScheduleEntries->Reset();
sl@0: 		//
sl@0: 		// Populate the schedule entry array with a varying list of 
sl@0: 		// start-times, intervals, etc for this particular task
sl@0: 		//
sl@0: 		for(TInt j=0; j<aNumScheduleEntries; ++j)
sl@0: 			{
sl@0: 			TScheduleEntryInfo scheduleEntry = SchSvrHelpers::RandomScheduleEntryInfo(TheSeed);
sl@0: 			TTime now;
sl@0: 			now.HomeTime(); // sets now to home time
sl@0: 			//if iStartTime is set lower then 5 sec into the future, postpone iStartTime 10 sec into the future
sl@0: 			if(scheduleEntry.iStartTime < now + timeLimit) 
sl@0: 				scheduleEntry.iStartTime = now + timeToAdd; 
sl@0: 			aScheduleEntries->AppendL(scheduleEntry);
sl@0: 			}
sl@0: 		//
sl@0: 		// Create some dummy task data
sl@0: 		//
sl@0: 		HBufC* taskData = HBufC::NewLC(KTaskDataPrefix().Length()+4);
sl@0: 		taskData->Des().Copy(KTaskDataPrefix());
sl@0: 		taskData->Des().AppendNum(i);
sl@0: 		//
sl@0: 		// Munge the task name
sl@0: 		//
sl@0: 		TTaskInfo taskInfo;
sl@0: 		taskInfo.iName = *taskData;
sl@0: 		taskInfo.iRepeat = 1;
sl@0: 		taskInfo.iPriority = 1;
sl@0: 		// Schedule the transient task
sl@0: 		TSchedulerItemRef scheduleReference;
sl@0: 		TInt result = TheScheduler.ScheduleTask(taskInfo, 
sl@0: 												*taskData, 
sl@0: 												scheduleReference, 
sl@0: 												*aScheduleEntries);
sl@0: 		TEST2(result, KErrNone);
sl@0: 		TheTest.Printf(_L("TaskId: %d => TaskName: %S\n"), taskInfo.iTaskId, &taskInfo.iName);
sl@0: 		CleanupStack::PopAndDestroy(taskData);
sl@0: 		//
sl@0: 		// Save the taskInfo so we can check it later - this inserts the taskinfo into
sl@0: 		// the array (preserves sorted order by TTaskInfo.iTaskId) but also has the
sl@0: 		// added bonus of preventing duplicate task ids...
sl@0: 		//
sl@0: 		aTaskInfos->InsertIsqL(taskInfo, KTaskInfoSortKey);
sl@0: 		// Disable all schedules once added, just to stop them going off
sl@0: 		// and therefore being deleted when we are trying to compare them 
sl@0: 		result = TheScheduler.DisableSchedule(scheduleReference.iHandle);
sl@0: 		TEST2(result, KErrNone);
sl@0: 		// Save the sever generated schedule reference and taskId for checking later
sl@0: 		aScheduleReferences->AppendL(scheduleReference);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: static void CheckScheduledRefs(TInt aNumSchedules)
sl@0: 	{
sl@0: 	CSchItemRefArray* refs = new (ELeave) CSchItemRefArray(3);
sl@0: 	CleanupStack::PushL(refs);
sl@0: 	TInt res = TheScheduler.GetScheduleRefsL(*refs, EAllSchedules); 
sl@0: 	TEST2(res, KErrNone);
sl@0: 	TInt count = refs->Count();
sl@0: 	TEST(count == aNumSchedules);
sl@0: 	CleanupStack::PopAndDestroy(refs);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1342
sl@0: @SYMTestCaseDesc	    Scheduling tasks test
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Tests for RScheduler::GetTaskDataSize(),RScheduler::GetTaskInfoL() functions
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void TestScheduledTasksL(TInt aNumSchedules,
sl@0: 								CArrayFixFlat<TTaskInfo>* aTaskInfos)
sl@0: 	{
sl@0: 	for(TInt n=0; n<aNumSchedules; ++n)
sl@0: 		{
sl@0: 		const TTaskInfo& taskInfo = aTaskInfos->At(n);
sl@0: 		TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1342 "));
sl@0: 
sl@0: 		// First retrieve the task size
sl@0: 		TInt taskSize;
sl@0: 		TInt result = TheScheduler.GetTaskDataSize(taskInfo.iTaskId, taskSize);
sl@0: 		TEST2(result, KErrNone);
sl@0: 		TEST(taskSize > 0);
sl@0: 
sl@0: 		// Next retrieve the task info associated with a particular task Id
sl@0: 		HBufC* taskData = HBufC::NewLC(taskSize);
sl@0: 		TPtr pTaskData = taskData->Des();
sl@0: 
sl@0: 		TTime scheduleNextDueTime;
sl@0: 		TTaskInfo taskFromServer;
sl@0: 		TSchedulerItemRef scheduleReference;
sl@0: 
sl@0: 		result = TheScheduler.GetTaskInfoL(taskInfo.iTaskId,
sl@0: 										   taskFromServer, 
sl@0: 										   pTaskData, 
sl@0: 										   scheduleReference, 
sl@0: 										   scheduleNextDueTime);
sl@0: 		TEST2(result, KErrNone);
sl@0: 		TEST(taskData->Length() == taskSize);
sl@0: 
sl@0: 		// Now check that the task returned by the server matches that held locallly....
sl@0: 		TBool bbb = SchSvrHelpers::IsTaskInfoTheSame(taskFromServer, taskInfo);
sl@0: 		if(!bbb)
sl@0: 			{
sl@0: 			RDebug::Print(_L("TaskInfo1. repeat=%x, id=%d, name=%S, priority=%x\n"),
sl@0: 				taskFromServer.iRepeat, taskFromServer.iTaskId, &taskFromServer.iName, taskFromServer.iPriority);
sl@0: 			RDebug::Print(_L("TaskInfo2. repeat=%x, id=%d, name=%S, priority=%x\n"),
sl@0: 				taskInfo.iRepeat, taskInfo.iTaskId, &taskInfo.iName, taskInfo.iPriority);
sl@0: 			}
sl@0: 		TEST(bbb);
sl@0: 		
sl@0: 		// Check taskData is the same (was originally held in the TTaskInfo.iName field)
sl@0: 		const TDesC& des1 = taskInfo.iName;
sl@0: 		TDes& des2 = pTaskData;
sl@0: 		TEST(des1 == des2);
sl@0: 		CleanupStack::PopAndDestroy(taskData);
sl@0: 		}
sl@0: 	}
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-1040
sl@0: @SYMTestCaseDesc	    Tests for retrieving of task data and info.
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    Create a large number of transient scheduled tasks to test Id generation
sl@0:                         Tests tasks for a given taskid is the same
sl@0: 						Tests reference can be retrieved for a given handle.
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */		
sl@0: static void Test8L()
sl@0: 	{
sl@0: 	// Test title
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-1040 Create a large number of tasks, test retrieval of task data and task info "));
sl@0: 	
sl@0: 	SchSvrHelpers::DeleteAllSchedulesL(TheScheduler);
sl@0: 
sl@0: 	// Constants used in this function
sl@0: 	const TInt KNumberOfSchedulesToCreate		= 20;
sl@0: 	const TInt KNumberOfScheduleEntriesToCreate = 5;
sl@0: 
sl@0: 	// Prepare arrays required for the tests below
sl@0: 	CSchEntryInfoArray* scheduleEntries = ::CreateSchEntryInfoArrayLC(KNumberOfScheduleEntriesToCreate);
sl@0: 	CArrayFixFlat<TTaskInfo>* taskInfos = ::CreateTaskInfoLC(KNumberOfSchedulesToCreate);
sl@0: 	CSchItemRefArray* scheduleReferences = ::CreateScheduleRefsLC(KNumberOfSchedulesToCreate);
sl@0: 
sl@0: 	//
sl@0: 	// Create a large number of transient scheduled tasks 
sl@0: 	// to test Id generation
sl@0: 	//
sl@0: 	::CreateTransientScheduledTasksL(KNumberOfScheduleEntriesToCreate,
sl@0: 									 KNumberOfSchedulesToCreate,
sl@0: 									 scheduleEntries,
sl@0: 									 taskInfos,
sl@0: 									 scheduleReferences);
sl@0: 
sl@0: 
sl@0: 	::CheckScheduledRefs(KNumberOfSchedulesToCreate);
sl@0: 
sl@0: 	// Test tasks for a given taskid is the same
sl@0: 	::TestScheduledTasksL(KNumberOfSchedulesToCreate, taskInfos);
sl@0: 
sl@0: 	// Test reference can be retrieved for a given handle.
sl@0: 	CleanupStack::PopAndDestroy(scheduleReferences);
sl@0: 	CleanupStack::PopAndDestroy(taskInfos);
sl@0: 	CleanupStack::PopAndDestroy(scheduleEntries);
sl@0: 
sl@0: 	// now delete all schedules
sl@0: 	SchSvrHelpers::DeleteAllSchedulesL(TheScheduler);
sl@0: 	TInt ccc = CountScheduledItemsL(EAllSchedules, TheScheduler);
sl@0: 	TEST(ccc == 0);
sl@0: 
sl@0: 	SchSvrHelpers::Pause(TheTest);
sl@0: 	}
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-SCHSVR-CT-3544
sl@0: @SYMTestCaseDesc	    This test establishes transient tasks do not persist to disk.
sl@0: @SYMTestPriority 	    High
sl@0: @SYMTestActions  	    create persistent and transient schedules with tasks. Wait for tasks to execute.
sl@0: 			    Cause server to shutdown and restart. Check file size against known good size.
sl@0: @SYMTestExpectedResults Persistent schedules and tasks are saved to file, but transient ones are not.
sl@0: @SYMDEF                 DEF109371
sl@0: */		
sl@0: static void Test9L()
sl@0: 	{
sl@0: //Clean up before running test
sl@0: 	SchSvrHelpers::DeleteScheduleFilesL();
sl@0: 	TheScheduler.Close();
sl@0: 	
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-SCHSVR-CT-3544 Test transient schedules and tasks do not persist after power outages "));
sl@0: 	
sl@0: 	TheTest.Next(_L("Connect to Scheduler"));
sl@0: 	TInt res = TheScheduler.Connect();
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Registering Client"));
sl@0: 	TEST2(SchSvrHelpers::RegisterClientL(TheScheduler), KErrNone);
sl@0: 
sl@0: 
sl@0: 	//Create a transient schedule with a task set to go off 10 minutes from server time.
sl@0: 	const TDateTime KTimeToStartTask(2000, EJanuary, 10, 15, 30, 0, 0);
sl@0: 
sl@0: 	TSchedulerItemRef schedulerItemReference;
sl@0: 	CSchEntryInfoArray* entryArray = new(ELeave) CSchEntryInfoArray(1);
sl@0: 	CleanupStack::PushL(entryArray);
sl@0: 	
sl@0: 	HBufC* taskData = _L("This is some transient task data created for testing").AllocL();
sl@0: 	CleanupStack::PushL(taskData);
sl@0: 	
sl@0: 	// Prepare the task info - this describes the tasks that are contained within the task
sl@0: 	// entry array
sl@0: 	TTaskInfo taskInfo = SchSvrHelpers::TaskInfo(_L("A transient test task"), 100);
sl@0: 		
sl@0: 	// Create a schedule entry and append it to the entry array
sl@0: 	{
sl@0: 	TScheduleEntryInfo scheduleEntry = SchSvrHelpers::ScheduleEntryInfo(EDaily, TTime(KTimeToStartTask), 7, 2);
sl@0: 	entryArray->AppendL(scheduleEntry);
sl@0: 	}
sl@0: 
sl@0: 	// Create the transient task
sl@0: 	TInt ret = TheScheduler.ScheduleTask(taskInfo, *taskData, schedulerItemReference, *entryArray);
sl@0: 	TEST2(ret, KErrNone);
sl@0: 
sl@0: 	// Check that the task Id after scheduling the event is not 
sl@0: 	// the same as it was prior to the requesting the service
sl@0: 	TEST(taskInfo.iTaskId != -1);
sl@0: 
sl@0: 
sl@0: 	// Create a persistent schedule
sl@0: 	TheTest.Next(_L("Creating Persistent schedule"));
sl@0: 	//Set server time to known time
sl@0: 	SchSvrHelpers::SetHomeTimeL(TTime(TDateTime(2000, EJanuary, 1, 10, 5, 0, 0))); // 10:05 am
sl@0: 
sl@0: 	TSchedulerItemRef scheduleHandle;
sl@0: 	TTime time;
sl@0: 	time.HomeTime();//Get time
sl@0: 	time += TTimeIntervalSeconds(5); //Task to go off five seconds from now
sl@0: 	User::LeaveIfError(CreateScheduleL(scheduleHandle, TheScheduler, time)); 
sl@0: 
sl@0: 	// Add a repeating task to the persistent schedule
sl@0: 	TheTest.Next(_L("Creating task for persistent schedule"));
sl@0: 	TTaskInfo persisttaskInfo;
sl@0: 	{
sl@0: 	persisttaskInfo.iName = _L("MyPersistent TaskName");
sl@0: 	persisttaskInfo.iPriority = 2;
sl@0: 	persisttaskInfo.iTaskId = 0;
sl@0: 	persisttaskInfo.iRepeat = 3;
sl@0: 	HBufC* data = _L("Persistent Task Data").AllocLC();
sl@0: 	TInt res = TheScheduler.ScheduleTask(persisttaskInfo, *data, scheduleHandle.iHandle);
sl@0: 	CleanupStack::PopAndDestroy(); // data
sl@0: 	TEST2(res, KErrNone);
sl@0: 	}
sl@0: 	
sl@0: 	//Now get the filesize of the servers schedule.dat.
sl@0: 	TFileName templateFileName;
sl@0: 	_LIT(KFileName,"C:\\private\\10005399\\SchedulesBackup.dat");
sl@0: 	templateFileName.Copy(KFileName);
sl@0: 	templateFileName[0] = 'A' + static_cast<TInt>(RFs::GetSystemDrive());
sl@0: 	RFile file;
sl@0: 	CleanupClosePushL(file);
sl@0: 	
sl@0: 	SchSvrHelpers::Pause(TheTest);
sl@0: 	//AllFiles capability required to access the private cage of the server
sl@0: 	TInt ferr = file.Open(TheFsSession, templateFileName, EFileShareReadersOrWriters | EFileRead);
sl@0: 	TEST2(ferr,KErrNone);
sl@0: 	TInt filesize1 = 0;
sl@0: 	//The below const is the measured file size for the creation of the above schedule.
sl@0: 	//It will change if new data members are added to task or schedule classes
sl@0: 	const TInt KExpectedFileSize = 374;
sl@0: 	TInt sErr = file.Size(filesize1);
sl@0: 	TEST2(sErr,KErrNone);
sl@0: 	TheTest.Printf(_L("Expected filesize is 374b Filesize is [%db]\n"), filesize1);
sl@0: 	TEST(filesize1 == KExpectedFileSize);
sl@0: 
sl@0: 	CleanupStack::PopAndDestroy(3);
sl@0: }
sl@0: 
sl@0: 
sl@0: //***********************************************************************************
sl@0: static TInt RunTestsL()
sl@0: 	{
sl@0: 	TheTest.Next(_L("Delete old files"));
sl@0: 	SchSvrHelpers::DeleteScheduleFilesL();
sl@0: 	
sl@0: 	TheTest.Next(_L("Create Task notification semaphore"));
sl@0: 	//initialise task notification semaphore
sl@0: 	STaskSemaphore sem;
sl@0: 	sem.CreateL();
sl@0: 
sl@0: 	// Prepare random number seed
sl@0: 	TheTest.Next(_L("Prepare random number"));
sl@0: 	TTime now;
sl@0: 	now.UniversalTime();
sl@0: 	TheSeed = now.Int64();
sl@0: 
sl@0: 	// Connect to the server
sl@0: 	TheTest.Next(_L("===== Connect to Scheduler ====="));
sl@0: 	TInt res = TheScheduler.Connect();
sl@0: 	TEST2(res, KErrNone);
sl@0: 	
sl@0: 	// Register a client with the server
sl@0: 	TheTest.Next(_L("===== Registering Client ====="));
sl@0: 	res = SchSvrHelpers::RegisterClientL(TheScheduler);
sl@0: 	TEST2(res, KErrNone);
sl@0: 
sl@0: 	TheTest.Next(_L("Start tests"));
sl@0: 	Test1L();
sl@0: 	Test2L();
sl@0: 	Test3L();
sl@0: 	Test4L();
sl@0: 	Test5L();
sl@0: 	Test6L();
sl@0: 	Test7L();
sl@0: 	Test8L();
sl@0: 	Test9L();
sl@0: 
sl@0: 	TheTest.Next(_L("Tidying up"));
sl@0: 	//Tidying up so next test will be clear.
sl@0: 	TheTest.Next(_L("Delete all schedules"));
sl@0: 	SchSvrHelpers::DeleteAllSchedulesL(TheScheduler);
sl@0: 	SchSvrHelpers::Pause(TheTest, 2);
sl@0: 	TheTest.Next(_L("Delete old files\n"));
sl@0: 	SchSvrHelpers::DeleteScheduleFilesL();
sl@0: 
sl@0: 	TheScheduler.Close();
sl@0: 	
sl@0: 	//close handle to semaphore
sl@0: 	sem.Close();
sl@0: 
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: //***********************************************************************************
sl@0: GLDEF_C TInt E32Main()
sl@0: //	
sl@0: // TheTest the scheduler
sl@0: //
sl@0:     {
sl@0: 	__UHEAP_MARK;
sl@0: 	TheTest.Start(_L("TC_TSCH_SCHEDULING2"));
sl@0: 	TheTest.Title();
sl@0: 	TheCleanup = CTrapCleanup::New();
sl@0: 	//If the previous test fails, SCHSVR.exe may stay in memory.
sl@0: 	TRAPD(error,CleanupHelpers::TestCleanupL());
sl@0: 	TEST2(error, KErrNone);
sl@0: 
sl@0: 	TEST2(TheFsSession.Connect(), KErrNone);;
sl@0: 	TRAP(error, RunTestsL());	
sl@0: 	TRAP(error,CleanupHelpers::TestCleanupL());
sl@0: 	TEST2(error, KErrNone);
sl@0: 	delete TheCleanup;
sl@0: 	
sl@0: 	TheFsSession.Close();
sl@0: 	TheTest.End();
sl@0: 	TheTest.Close();
sl@0: 	__UHEAP_MARKEND;
sl@0: 	return(KErrNone);
sl@0: 	}