sl@0: // Copyright (c) 2003-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\debug\t_eventtracker.cpp sl@0: // User-side harness for a LDD-based debug agent which keeps sl@0: // track of various events (e.g. thread creation) and tests sl@0: // them for consistency (e.g. a thread deletion event should be sl@0: // preceded with a thread creation one). sl@0: // USAGE: sl@0: // 1. start t_eventtracker usehook sl@0: // to hook event tracker to the stop-mode debugger breakpoint, or sl@0: // start t_eventtracker sl@0: // to add it to the kernel event handler queue sl@0: // 2. << do something e.g. run some tests >> sl@0: // 3. t_eventtracker stop sl@0: // KNOWN ISSUES: sl@0: // * The debug agent allocates memory on the kernel heap. sl@0: // Consequently, it will perturbate any test using sl@0: // __KHEAP_FAILNEXT() (e.g. t_kheap). sl@0: // * There is a window of opportunity when tracking is started sl@0: // or stopped during which some events may be lost, leading sl@0: // to incorrect results. Therefore t_eventtracker should sl@0: // be called only when the system is idle. sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include "reventtracker.h" sl@0: sl@0: RTest test(_L("T_EVENTTRACKER")); sl@0: sl@0: _LIT(KTrackerServerName, "EventTrackerServer"); sl@0: sl@0: ////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: /** Wrapper around LDD session with debug agent */ sl@0: sl@0: class CTracker : public CBase sl@0: { sl@0: public: sl@0: ~CTracker(); sl@0: void Start(TBool aUseHook); sl@0: TInt Stop(); sl@0: private: sl@0: REventTracker iEventTracker; sl@0: }; sl@0: sl@0: CTracker::~CTracker() sl@0: { sl@0: iEventTracker.Close(); sl@0: } sl@0: sl@0: void CTracker::Start(TBool aUseHook) sl@0: { sl@0: TInt r = User::LoadLogicalDevice(_L("D_EVENTTRACKER.LDD")); sl@0: test(r == KErrNone || r == KErrAlreadyExists); sl@0: sl@0: test(iEventTracker.Open(aUseHook) == KErrNone); sl@0: test(iEventTracker.Start() == KErrNone); sl@0: } sl@0: sl@0: TInt CTracker::Stop() sl@0: { sl@0: TInt r=iEventTracker.Stop(); sl@0: iEventTracker.Close(); sl@0: return r; sl@0: } sl@0: sl@0: ////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: sl@0: /** Server used to interact with the debug agent */ sl@0: sl@0: class CTrackerServer : public CServer2 sl@0: { sl@0: public: sl@0: static CTrackerServer* NewLC(TBool aUseHook); sl@0: ~CTrackerServer(); sl@0: // from CServer2 sl@0: CSession2* NewSessionL(const TVersion& aVersion,const RMessage2&) const; sl@0: private: sl@0: CTrackerServer(); sl@0: public: sl@0: CTracker* iTracker; sl@0: }; sl@0: sl@0: /** Session used to stop event tracking */ sl@0: sl@0: class CTrackerSession : public CSession2 sl@0: { sl@0: private: sl@0: // from CSession2 sl@0: void ServiceL(const RMessage2& aMessage); sl@0: }; sl@0: sl@0: void CTrackerSession::ServiceL(const RMessage2& aMessage) sl@0: { sl@0: TInt r = ((CTrackerServer*)Server())->iTracker->Stop(); sl@0: CActiveScheduler::Stop(); sl@0: aMessage.Complete(r); sl@0: } sl@0: sl@0: CTrackerServer* CTrackerServer::NewLC(TBool aUseHook) sl@0: { sl@0: CTrackerServer* server = new(ELeave) CTrackerServer; sl@0: CleanupStack::PushL(server); sl@0: server->iTracker = new(ELeave) CTracker; sl@0: server->StartL(KTrackerServerName); sl@0: server->iTracker->Start(aUseHook); sl@0: return server; sl@0: } sl@0: sl@0: CTrackerServer::CTrackerServer() sl@0: : CServer2(EPriorityStandard) sl@0: { sl@0: } sl@0: sl@0: CTrackerServer::~CTrackerServer() sl@0: { sl@0: delete iTracker; sl@0: } sl@0: sl@0: CSession2* CTrackerServer::NewSessionL(const TVersion& /*aVersion*/,const RMessage2&) const sl@0: { sl@0: return new(ELeave) CTrackerSession; sl@0: } sl@0: sl@0: ////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: /** Handle to client/server session */ sl@0: sl@0: class RTracker : public RSessionBase sl@0: { sl@0: public: sl@0: TInt Open() { return CreateSession(KTrackerServerName, TVersion(), 0); } sl@0: TInt Stop() { return SendReceive(0); } sl@0: }; sl@0: sl@0: ////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void MainL() sl@0: { sl@0: _LIT(KStop,"stop"); sl@0: _LIT(KUseHook,"usehook"); sl@0: TBuf<64> c; sl@0: User::CommandLine(c); sl@0: if (c.FindF(KStop) >= 0) sl@0: { sl@0: // Stop event tracking sl@0: RTracker t; sl@0: test(t.Open() == KErrNone); sl@0: test(t.Stop() == KErrNone); sl@0: t.Close(); sl@0: } sl@0: else sl@0: { sl@0: // Create server and start event tracking sl@0: test(User::RenameThread(KTrackerServerName) == KErrNone); sl@0: sl@0: TBool useHook = EFalse; sl@0: if (c.FindF(KUseHook) >= 0) sl@0: { sl@0: useHook = ETrue; sl@0: } sl@0: sl@0: CTrackerServer* server = CTrackerServer::NewLC(useHook); sl@0: sl@0: CActiveScheduler::Start(); sl@0: sl@0: CleanupStack::PopAndDestroy(server); sl@0: } sl@0: } sl@0: sl@0: sl@0: TInt E32Main() sl@0: { sl@0: test.Title(); sl@0: sl@0: __UHEAP_MARK; sl@0: sl@0: CTrapCleanup* cleanup = CTrapCleanup::New(); sl@0: test(cleanup != NULL); sl@0: CActiveScheduler* scheduler = new CActiveScheduler; sl@0: test(scheduler != NULL); sl@0: CActiveScheduler::Install(scheduler); sl@0: sl@0: TRAPD(r, MainL()); sl@0: if (r != KErrNone) sl@0: { sl@0: test.Printf(_L("Unexpected leave: %d\n"), r); sl@0: test(EFalse); sl@0: } sl@0: sl@0: delete scheduler; sl@0: delete cleanup; sl@0: sl@0: __UHEAP_MARKEND; sl@0: sl@0: return 0; sl@0: }