--- /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;
+ }