sl@0: // Copyright (c) 2005-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_debugapi.cpp sl@0: // User-side harness for LDD-based debug agent that checks debug API sl@0: // interface provided by kernel extension kdebug.dll (ARMv5) or kdebugv6 (ARMv6). sl@0: // It uses debug port to print the list of processes, threads, etc. sl@0: // Usage: t_debugapi [process] [thread] [chunk] [ipaccess] sl@0: // Performs all steps if there are no input arguments. sl@0: // The test is automated (does not require any input argument or manual assistance, but needs sl@0: // non-standard image file that includes kdebug.dll (ARMv5 based target) or kdebugV6.dll sl@0: // (ARMv6 based target). It can be achieved by adding: #define STOP_MODE_DEBUGGING in .oby/iby file. sl@0: // Supported and tested on H2 (ARMv5) and integrator_1136 (ARMv6) platforms. sl@0: // It requires D_DEBUGAPI.DLL as well. sl@0: // Using debug interfaca only, it completes (prints) the list of: sl@0: // - processes; sl@0: // - threads; sl@0: // - chunks; sl@0: // in the system. On multiple-memory-model based target (ARMv6 architecture), sl@0: // it also reads from address space of another process. This part is not checked sl@0: // on moving-memory-model target (ARMv5) (e.g. always passes). sl@0: // Note: The test may cause system fail on ARM1136(r0p2) with L210 cache due to Erratum 317041. sl@0: // In that case, uncomment two relevant lines in DDebugAPIChecker::ReadFromOtherProcessArmv6 (in sl@0: // d_debugapi.cia) and rebuild d_debugapi.ldd. sl@0: // sl@0: // sl@0: sl@0: //! @file t_debugapi.h sl@0: //! @SYMTestCaseID KBASE/T_DEBUGAPI sl@0: //! @SYMTestType UT sl@0: //! @SYMTestCaseDesc sl@0: //! @SYMREQ PREQ835 sl@0: //! @SYMTestActions sl@0: //! @SYMTestExpectedResults Test program completes with no errors. sl@0: //! @SYMTestPriority Low sl@0: //! @SYMTestStatus Defined sl@0: sl@0: sl@0: #include sl@0: #include "d_debugapi.h" sl@0: sl@0: RTest test(_L("T_DebugAPI")); sl@0: sl@0: _LIT(KProcessName,"t_DebugAPI.exe"); sl@0: _LIT(KProcess,"Process"); sl@0: _LIT(KChunk,"Chunk"); sl@0: _LIT(KThread,"Thread"); sl@0: _LIT(KIPAccess,"IPAccess"); sl@0: _LIT(KIPAccessStep2,"IPAccessStep2"); sl@0: sl@0: TBuf<64> command; sl@0: sl@0: //The main program for the first instance of the process. sl@0: void Main() sl@0: { sl@0: RDebugAPIChecker debugAPI; sl@0: TInt r; sl@0: TBool checkAll = EFalse; sl@0: sl@0: if (command.Length() == 0) sl@0: checkAll = ETrue; sl@0: sl@0: r = User::LoadLogicalDevice(_L("D_DebugAPI.LDD")); sl@0: test(r == KErrNone || r == KErrAlreadyExists); sl@0: test (debugAPI.Open() == KErrNone); sl@0: sl@0: if (checkAll || command.FindF(KProcess) >= 0) sl@0: { sl@0: test.Next(_L("Printing process info")); sl@0: test(debugAPI.Process() == KErrNone); sl@0: } sl@0: sl@0: if (checkAll || command.FindF(KChunk) >= 0) sl@0: { sl@0: test.Next(_L("Printing chunk info")); sl@0: test(debugAPI.Chunk() == KErrNone); sl@0: } sl@0: sl@0: if (checkAll || command.FindF(KThread) >= 0) sl@0: { sl@0: test.Next(_L("Printing thread info")); sl@0: test(debugAPI.Thread() == KErrNone); sl@0: } sl@0: sl@0: if (checkAll || command.FindF(KIPAccess) >= 0) sl@0: { sl@0: test.Next(_L("KIPAccess")); sl@0: sl@0: RProcess process; sl@0: TRequestStatus status; sl@0: sl@0: //The other process will try to read this variable. sl@0: TInt probeVariable = 0x55555555; sl@0: TUint id = process.Id(); sl@0: TBuf<64> command; sl@0: command.Format(_L("%08x %08x %08x IPAccessStep2"), id, &probeVariable, probeVariable); sl@0: sl@0: test(process.Create(KProcessName, command) == KErrNone); sl@0: process.Logon(status); sl@0: process.Resume(); sl@0: User::WaitForRequest(status); sl@0: test(process.ExitType() == EExitKill); sl@0: test(process.ExitReason() == KErrNone); sl@0: process.Close(); sl@0: sl@0: //Now try another value. sl@0: probeVariable = 0xaaaaaaaa; sl@0: command.Format(_L("%08x %08x %08x IPAccessStep2"), id, &probeVariable, probeVariable); sl@0: sl@0: test(process.Create(KProcessName, command) == KErrNone); sl@0: process.Logon(status); sl@0: process.Resume(); sl@0: User::WaitForRequest(status); sl@0: test(process.ExitType() == EExitKill); sl@0: test(process.ExitReason() == KErrNone); sl@0: process.Close(); sl@0: } sl@0: sl@0: debugAPI.Close(); sl@0: r = User::FreeLogicalDevice(KTestLddName); sl@0: test(r == KErrNone || r == KErrNotFound); sl@0: } sl@0: sl@0: /** sl@0: The main program for the second instance of the process. sl@0: We need two processes two check inter-process data access. sl@0: */ sl@0: void SecondProcessMain() sl@0: { sl@0: RDebugAPIChecker debugAPI; sl@0: TInt r; sl@0: sl@0: r = User::LoadLogicalDevice(_L("D_DebugAPI.LDD")); sl@0: test(r == KErrNone || r == KErrAlreadyExists); sl@0: test (debugAPI.Open() == KErrNone); sl@0: sl@0: if (command.FindF(KIPAccessStep2) >= 0) sl@0: { sl@0: RDebugAPIChecker::IPAccessArgs args; sl@0: sl@0: TPtrC ptr = command.Mid(0,8); sl@0: TLex lex(ptr); sl@0: lex.Val(args.iProcessID, EHex); sl@0: sl@0: ptr.Set(command.Mid(9,8)); sl@0: lex.Assign(ptr); sl@0: lex.Val(args.iAddress, EHex); sl@0: sl@0: ptr.Set(command.Mid(18,8)); sl@0: lex.Assign(ptr); sl@0: lex.Val(args.iValue, EHex); sl@0: sl@0: r = debugAPI.IPAccess(&args); sl@0: test(r == KErrNone || r==KErrNotSupported); sl@0: } sl@0: sl@0: debugAPI.Close(); sl@0: r = User::FreeLogicalDevice(KTestLddName); sl@0: } sl@0: sl@0: TInt E32Main() sl@0: { sl@0: test.Title(); sl@0: __UHEAP_MARK; sl@0: sl@0: User::CommandLine(command); sl@0: sl@0: if (command.FindF(KIPAccessStep2) < 0) //The second process is recognized by the specific input parameter sl@0: { sl@0: //This is the first instance of the running process. sl@0: test.Start(_L("Testing Debug API")); sl@0: Main(); sl@0: test.End(); sl@0: } sl@0: else sl@0: { sl@0: //This is the second instance of the running process. sl@0: SecondProcessMain(); sl@0: } sl@0: sl@0: __UHEAP_MARKEND; sl@0: return 0; sl@0: }