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 the License "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: // e32test\system\t_dobject.cpp sl@0: // Overview: sl@0: // Test RObjectIx strategy of memory reallocation and sl@0: // free list maintenance. sl@0: // Test DObjectCon findhandle methods sl@0: // API Information: sl@0: // DObject, RObjectIx sl@0: // Details: sl@0: // - Add a number of DObjects to RObjectIx, then remove them sl@0: // in the same order. Verify results are as expected. Time sl@0: // how long the process takes to complete. sl@0: // - Add a number of DObjects to RObjectIx, then remove them sl@0: // in the reverse order. Verify results are as expected. Time sl@0: // how long the process takes to complete. sl@0: // - Add and remove a random number of DObjects to/from RObjectIx. sl@0: // Time how long the process takes to complete. sl@0: // Platforms/Drives/Compatibility: sl@0: // All. sl@0: // Assumptions/Requirement/Pre-requisites: sl@0: // Failures and causes: sl@0: // Base Port information: sl@0: // sl@0: // sl@0: sl@0: #define __E32TEST_EXTENSION__ sl@0: #include sl@0: #include sl@0: #include "d_dobject.h" sl@0: sl@0: LOCAL_D RTest test(_L("T_DOBJECT")); sl@0: sl@0: TInt TestRObjectIxAccess(TAny* aRObjectIxPtr) sl@0: { sl@0: const TInt KConcurrentDObjectTestRepeats = 1; sl@0: sl@0: RTestDObject ldd; sl@0: TInt ret; sl@0: sl@0: ret = ldd.Open(); sl@0: if (ret == KErrNone) sl@0: { sl@0: for (TInt repeat = 0; repeat < KConcurrentDObjectTestRepeats; repeat++) sl@0: { sl@0: ret = ldd.RObjectIxThreadTestExerciseIx(aRObjectIxPtr); sl@0: if (ret != KErrNone) sl@0: { sl@0: break; sl@0: } sl@0: } sl@0: ldd.Close(); sl@0: } sl@0: sl@0: return ret; sl@0: } // TestRObjectIxAccess sl@0: sl@0: void TestConcurrentRObjectIxAccess(RTestDObject& aLdd) sl@0: { sl@0: const TInt KConcurrentDObjectThreads = 4; sl@0: _LIT(KConcurrentDObjectThreadName, "T_DObject_Thread"); sl@0: sl@0: TInt ret; sl@0: sl@0: // sl@0: // Create a RObjectIx in the driver (pointer not valid user side!)... sl@0: // sl@0: void* objectIxPtr = NULL; sl@0: sl@0: ret = aLdd.RObjectIxThreadTestCreateIx(objectIxPtr); sl@0: test_KErrNone(ret); sl@0: sl@0: // sl@0: // Run KConcurrentDObjectThreads number of threads which random add/remove sl@0: // DObjects to the same RObjectIx... sl@0: // sl@0: RThread threadHandle[KConcurrentDObjectThreads]; sl@0: TRequestStatus status[KConcurrentDObjectThreads]; sl@0: TBuf<32> threadName; sl@0: TInt thread; sl@0: sl@0: for (thread = 0; thread < KConcurrentDObjectThreads; thread++) sl@0: { sl@0: threadName.Copy(KConcurrentDObjectThreadName); sl@0: threadName.AppendNum(thread); sl@0: sl@0: ret = threadHandle[thread].Create(threadName, TestRObjectIxAccess, KDefaultStackSize, NULL, objectIxPtr); sl@0: test_KErrNone(ret); sl@0: sl@0: threadHandle[thread].Logon(status[thread]); sl@0: } sl@0: sl@0: // sl@0: // The test thread must be higher priority to ensure all the threads start. sl@0: // All the threads are then resumed and allowed to run to completion... sl@0: // sl@0: RThread().SetPriority(EPriorityMore); sl@0: sl@0: for (thread = 0; thread < KConcurrentDObjectThreads; thread++) sl@0: { sl@0: threadHandle[thread].Resume(); sl@0: } sl@0: sl@0: for (thread = 0; thread < KConcurrentDObjectThreads; thread++) sl@0: { sl@0: User::WaitForRequest(status[thread]); sl@0: test_KErrNone(status[thread].Int()); sl@0: CLOSE_AND_WAIT(threadHandle[thread]); sl@0: } sl@0: sl@0: RThread().SetPriority(EPriorityNormal); sl@0: sl@0: // sl@0: // Free the RObjectIx in the driver... sl@0: // sl@0: ret = aLdd.RObjectIxThreadTestFreeIx(objectIxPtr); sl@0: test_KErrNone(ret); sl@0: } // TestConcurrentRObjectIxAccess sl@0: sl@0: sl@0: void ListAllMutexes() sl@0: { sl@0: test.Printf(_L("Mutexes:\n")); sl@0: TFullName name; sl@0: TFindMutex find; sl@0: while (find.Next(name) == KErrNone) sl@0: { sl@0: test.Printf(_L(" %S (find handle == %08x)\n"), &name, find.Handle()); sl@0: } sl@0: } sl@0: sl@0: const TInt KObjectCount = 20; sl@0: _LIT(KDoubleMatch, "*double*"); sl@0: _LIT(KTrippleMatch, "*tripple*"); sl@0: sl@0: RMutex Mutexes[KObjectCount]; sl@0: TBuf<32> ObjectName; sl@0: sl@0: const TDesC& MutexName(TInt i) sl@0: { sl@0: ObjectName.Zero(); sl@0: ObjectName.AppendFormat(_L("Mutex_%02d"), i); sl@0: if (i % 2 == 0) sl@0: ObjectName.Append(_L("_double")); sl@0: if (i % 3 == 0) sl@0: ObjectName.Append(_L("_tripple")); sl@0: return ObjectName; sl@0: } sl@0: sl@0: void CreateMutexes() sl@0: { sl@0: for (TInt i = 0 ; i < KObjectCount ; ++i) sl@0: { sl@0: test(Mutexes[i].CreateGlobal(MutexName(i)) == KErrNone); sl@0: } sl@0: } sl@0: sl@0: void DeleteMutexes() sl@0: { sl@0: for (TInt i = 0 ; i < KObjectCount ; ++i) sl@0: { sl@0: Mutexes[i].Close(); sl@0: } sl@0: } sl@0: sl@0: void TestMutexesCreated() sl@0: { sl@0: test.Next(_L("Test mutexes have been created")); sl@0: sl@0: TFullName name; sl@0: sl@0: for (TInt i = 0 ; i < KObjectCount ; ++i) sl@0: { sl@0: TFindMutex find(MutexName(i)); sl@0: test(find.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find.Handle()); sl@0: } sl@0: } sl@0: sl@0: void TestMutexesDeleted() sl@0: { sl@0: test.Next(_L("Test mutexes deleted")); sl@0: sl@0: TFullName name; sl@0: sl@0: for (TInt i = 0 ; i < KObjectCount ; ++i) sl@0: { sl@0: TFindMutex find(MutexName(i)); sl@0: test(find.Next(name) == KErrNotFound); sl@0: } sl@0: } sl@0: sl@0: sl@0: void TestFindSpecificMutex() sl@0: { sl@0: test.Next(_L("Test finding specific mutexes")); sl@0: sl@0: for (TInt i = 0 ; i < KObjectCount ; ++i) sl@0: { sl@0: TFullName name; sl@0: TFindMutex find(MutexName(i)); sl@0: test(find.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find.Handle()); sl@0: test(name == MutexName(i)); sl@0: RMutex mutex; sl@0: test(mutex.Open(find) == KErrNone); sl@0: test(mutex.Name() == MutexName(i)); sl@0: mutex.Close(); sl@0: test(find.Next(name) == KErrNotFound); sl@0: } sl@0: } sl@0: sl@0: void TestFindMutexGroups() sl@0: { sl@0: test.Next(_L("Test finding groups of mutexes using wildcard name matching")); sl@0: sl@0: TFullName name; sl@0: TInt i; sl@0: sl@0: TFindMutex find2(KDoubleMatch); sl@0: for (i = 0 ; i < KObjectCount ; i += 2) sl@0: { sl@0: test(find2.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find2.Handle()); sl@0: test(name == MutexName(i)); sl@0: } sl@0: test(find2.Next(name) == KErrNotFound); sl@0: sl@0: TFindMutex find3(KTrippleMatch); sl@0: for (i = 0 ; i < KObjectCount ; i += 3) sl@0: { sl@0: test(find3.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find3.Handle()); sl@0: test(name == MutexName(i)); sl@0: } sl@0: test(find3.Next(name) == KErrNotFound); sl@0: } sl@0: sl@0: void TestMatchChange() sl@0: { sl@0: test.Next(_L("Test changing match half way through find")); sl@0: sl@0: sl@0: TFullName name; sl@0: TInt i; sl@0: sl@0: TFindMutex find(KDoubleMatch); sl@0: for (i = 0 ; i < KObjectCount/2 ; i += 2) sl@0: { sl@0: test(find.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find.Handle()); sl@0: test(name == MutexName(i)); sl@0: } sl@0: sl@0: find.Find(KTrippleMatch); sl@0: for (i = 0 ; i < KObjectCount ; i += 3) sl@0: { sl@0: test(find.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find.Handle()); sl@0: test(name == MutexName(i)); sl@0: } sl@0: test(find.Next(name) == KErrNotFound); sl@0: } sl@0: sl@0: void TestFindAndDeleteMutex1() sl@0: { sl@0: test.Next(_L("Test finding mutexes when the last found object has been deleted")); sl@0: sl@0: // Find and delete even mutexes sl@0: TFullName name; sl@0: TInt i; sl@0: for (i = 0 ; i < KObjectCount ; i += 2) sl@0: { sl@0: TFindMutex find2(MutexName(i)); sl@0: test(find2.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find2.Handle()); sl@0: Mutexes[i].Close(); sl@0: RMutex mutex; sl@0: test(mutex.Open(find2) == KErrNotFound); sl@0: } sl@0: sl@0: // Check odd mutexes remaining sl@0: for (i = 1 ; i < KObjectCount ; i += 2) sl@0: { sl@0: TFindMutex find(MutexName(i)); sl@0: test(find.Next(name) == KErrNone); sl@0: } sl@0: } sl@0: sl@0: void TestFindAndDeleteMutex2() sl@0: { sl@0: test.Next(_L("Test finding mutexes when the last found object has moved in the container")); sl@0: sl@0: // Find even mutexes and delete odd sl@0: TFullName name; sl@0: TInt i; sl@0: for (i = 0 ; i < KObjectCount ; i += 2) sl@0: { sl@0: TFindMutex find2(MutexName(i)); sl@0: test(find2.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find2.Handle()); sl@0: Mutexes[(i+KObjectCount-1)%KObjectCount].Close(); // -1%n = -1 or n-1, unspecified sl@0: RMutex mutex; sl@0: test(mutex.Open(find2) == KErrNone); sl@0: test(mutex.Name() == MutexName(i)); sl@0: mutex.Close(); sl@0: } sl@0: sl@0: // Check even mutexes remaining sl@0: for (i = 0 ; i < KObjectCount ; i += 2) sl@0: { sl@0: TFindMutex find(MutexName(i)); sl@0: test(find.Next(name) == KErrNone); sl@0: } sl@0: sl@0: } sl@0: sl@0: void TestFindWithCreation() sl@0: { sl@0: test.Next(_L("Test finding mutexes interleaved with creation")); sl@0: sl@0: TFullName name; sl@0: sl@0: for (TInt i = 0 ; i < KObjectCount ; ++i) sl@0: { sl@0: test(Mutexes[i].CreateGlobal(MutexName(i)) == KErrNone); sl@0: TFindMutex find(MutexName(i)); sl@0: test(find.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find.Handle()); sl@0: RMutex mutex; sl@0: test(mutex.Open(find) == KErrNone); sl@0: test(mutex.Name() == MutexName(i)); sl@0: mutex.Close(); sl@0: } sl@0: } sl@0: sl@0: void TestFindWithCreation2() sl@0: { sl@0: test.Next(_L("Test finding mutexes interleaved with creation and deletion")); sl@0: sl@0: TFullName name; sl@0: sl@0: for (TInt i = 0 ; i < KObjectCount ; ++i) sl@0: { sl@0: RMutex mutex; sl@0: test(mutex.CreateGlobal(MutexName(0)) == KErrNone); sl@0: TFindMutex find(MutexName(0)); sl@0: test(find.Next(name) == KErrNone); sl@0: test(name == MutexName(0)); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find.Handle()); sl@0: mutex.Close(); sl@0: sl@0: TFindMutex find2(MutexName(0)); sl@0: test(find2.Next(name) == KErrNotFound); sl@0: } sl@0: } sl@0: sl@0: void TestFindHandleOutOfRange() sl@0: { sl@0: test.Next(_L("Test finding mutexes when find handle index is off the end of container's array")); sl@0: sl@0: TFullName name; sl@0: sl@0: for (TInt i = 0 ; i < KObjectCount ; ++i) sl@0: { sl@0: TFindMutex find(MutexName(i)); sl@0: test(find.Next(name) == KErrNone); sl@0: test.Printf(_L(" %02d: found handle %08x\n"), i, find.Handle()); sl@0: RMutex mutex; sl@0: test(mutex.Open(find) == KErrNone); sl@0: test(mutex.Name() == MutexName(i)); sl@0: mutex.Close(); sl@0: sl@0: // towards the end, suddenly delete half the mutexes sl@0: if (i == (3 * KObjectCount) / 4) sl@0: { sl@0: for (TInt j = 0 ; j < KObjectCount / 2 ; ++j) sl@0: Mutexes[j].Close(); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void TestFindHandles() sl@0: { sl@0: test.Start(_L("Test FindHandle APIs using mutex classes")); sl@0: sl@0: CreateMutexes(); sl@0: ListAllMutexes(); sl@0: TestMutexesCreated(); sl@0: TestFindSpecificMutex(); sl@0: TestFindMutexGroups(); sl@0: TestMatchChange(); sl@0: DeleteMutexes(); sl@0: TestMutexesDeleted(); sl@0: sl@0: CreateMutexes(); sl@0: TestFindAndDeleteMutex1(); sl@0: DeleteMutexes(); sl@0: sl@0: CreateMutexes(); sl@0: TestFindHandleOutOfRange(); sl@0: DeleteMutexes(); sl@0: sl@0: CreateMutexes(); sl@0: TestFindAndDeleteMutex2(); sl@0: DeleteMutexes(); sl@0: sl@0: TestFindWithCreation(); sl@0: DeleteMutexes(); sl@0: sl@0: TestFindWithCreation2(); sl@0: TestMutexesDeleted(); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: SParam param; sl@0: TInt duration, r; sl@0: RTestDObject ldd; sl@0: sl@0: test.Title(); sl@0: sl@0: test.Start(_L("Loading test driver...")); sl@0: sl@0: r=User::LoadLogicalDevice(KDObjectTestLddName); sl@0: test(r==KErrNone || r==KErrAlreadyExists); sl@0: r=ldd.Open(); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("RObjectIxTest1 test ...")); sl@0: r=ldd.RObjectIxTest1(duration); sl@0: test(KErrNone==r); sl@0: test.Printf(_L("... completed in %d kernel ticks\n") , duration); sl@0: sl@0: test.Next(_L("RObjectIxTest2 test ...")); sl@0: r=ldd.RObjectIxTest2(duration); sl@0: test(KErrNone==r); sl@0: test.Printf(_L("... completed in %d kernel ticks\n") , duration); sl@0: sl@0: test.Next(_L("RObjectIxTest3 test (performance) ...")); sl@0: param.iSeed[0] = 0; sl@0: param.iSeed[1] = 1; sl@0: param.iPerformanceTest = ETrue; sl@0: r=ldd.RObjectIxTest3(param); sl@0: test(KErrNone==r); sl@0: test.Printf(_L("... completed in %d kernel ticks\n") , param.duration); sl@0: sl@0: test.Next(_L("RObjectIxTest3 test (random)...")); sl@0: param.iSeed[0]=User::TickCount(); sl@0: param.iSeed[1]=User::TickCount(); sl@0: param.iPerformanceTest = EFalse; sl@0: test.Printf(_L("... seeds=%xh and %xh ..."),param.iSeed[0],param.iSeed[1]); sl@0: r=ldd.RObjectIxTest3(param); sl@0: test(KErrNone==r); sl@0: test.Printf(_L("... completed in %d kernel ticks\n") , param.duration); sl@0: sl@0: test.Next(_L("RObjectIxTest4 test (reserved slots)...")); sl@0: test_KErrNone(ldd.RObjectIxTest4(duration)); sl@0: test.Printf(_L("... completed in %d kernel ticks\n") , duration); sl@0: sl@0: test.Next(_L("Test Concurrent access to RObjectIx")); sl@0: TestConcurrentRObjectIxAccess(ldd); sl@0: sl@0: test.Next(_L("Test Invalid handle look up")); sl@0: test_KErrNone(ldd.InvalidHandleLookupTest()); sl@0: sl@0: test.Next(_L("Test Kern::ValidateName and Kern::ValidateFullName")); sl@0: test_KErrNone(ldd.DObjectNameTest()); sl@0: sl@0: test.Next(_L("Closing test driver")); sl@0: ldd.Close(); sl@0: sl@0: test.Next(_L("FindHandles test")); sl@0: TestFindHandles(); sl@0: sl@0: test.End(); sl@0: sl@0: return(0); sl@0: }