dbgsrv/coredumpserver/plugins/formatters/dexc/test/tdexcformatter.cpp
changeset 0 c6b0df440bee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgsrv/coredumpserver/plugins/formatters/dexc/test/tdexcformatter.cpp	Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,522 @@
+// 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 <e32std.h>
+#include <e32base.h>
+#include "tdexcformatter.h"
+#include "dexcformatter.h"
+
+CDexcFormatterTest * CDexcFormatterTest::NewL(RTest &itest)
+{
+    CDexcFormatterTest *self = CDexcFormatterTest::NewLC(itest);
+    CleanupStack::Pop();
+    return self;
+}
+
+CDexcFormatterTest * CDexcFormatterTest::NewLC(RTest &itest)
+{
+    CDexcFormatterTest *self = new(ELeave) CDexcFormatterTest(itest);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+}
+
+void CDexcFormatterTest::ConstructL()
+{
+    server = new(ELeave) CTestCrashDataSource;
+    formatter = CDexcFormatter::NewL();
+    writer = CTestDataSave::NewL();
+    formatter->ConfigureDataSourceL(server);
+    formatter->ConfigureDataSaveL(writer);
+}
+
+CDexcFormatterTest::CDexcFormatterTest(RTest &aTest) : itest(aTest) { }
+
+CDexcFormatterTest::~CDexcFormatterTest()
+{
+    delete server;
+    delete writer;
+    delete formatter;
+}
+
+void CDexcFormatterTest::CleanupEComArray(TAny* aArray)
+{
+	(static_cast<RImplInfoPtrArray*> (aArray))->ResetAndDestroy();
+    REComSession::FinalClose();
+}
+
+void CDexcFormatterTest::TestSuiteL(TSuite aSuite) const
+{
+    RDebug::Print(_L("-> TestSuite(%d)\n"), aSuite);
+    TInt err;
+    TBuf<23> name(KTestName); 
+    name.AppendNum(aSuite);
+    itest.Next(name);
+
+    switch(aSuite)
+    {
+        case EConfigData:
+        {
+            RDebug::Print(_L("EConfigData starting...\n"));
+            TRAP(err, formatter->ConfigureDataSourceL(server));
+            itest(err == KErrNone);
+            itest(server == formatter->iDataSource);
+
+            TRAP(err, formatter->ConfigureDataSaveL(writer));
+            itest(err == KErrNone);
+            itest(writer == formatter->iDataSave);
+
+            TRAP(err, formatter->ConfigureDataSourceL(NULL)); 
+            itest(err == KErrNoMemory);
+
+            TRAP(err, formatter->ConfigureDataSaveL(NULL));
+            itest(err == KErrNoMemory);
+            RDebug::Print(_L("EConfigData passed!\n"));
+            break;
+        }
+
+        case EFindImplementation:
+        {
+		
+            RDebug::Print(_L("EFindImplementation starting...\n"));
+            RImplInfoPtrArray infoArray;
+            TCleanupItem cleanup(CDexcFormatterTest::CleanupEComArray, (TAny*)&infoArray);
+            CleanupStack::PushL(cleanup);
+            
+            TRAPD(err, CDexcFormatter::ListAllImplementationsL(infoArray));
+            itest(err == KErrNone);
+
+			CCoreDumpFormatter* findImpFormatter = 0;            
+            RBuf description;
+            description.CreateL(MaxPluginDescription);
+            CleanupClosePushL(description);
+
+            err = KErrNotFound;
+            for (TInt i = 0; i < infoArray.Count(); i++)
+            {
+                TUid uid = infoArray[i]->ImplementationUid();
+                findImpFormatter  = CCoreDumpFormatter::NewL(uid);
+				findImpFormatter->GetDescription(description);
+                delete findImpFormatter;
+                RDebug::Print(_L("found plugin[%d]: (%S)\n"), i, &description);
+                if(description == KPluginDescription())
+                {
+                    itest(uid == KDexcFormatterUid);
+                    err = KErrNone;
+                    break;
+                }
+                description.Zero();
+            }
+            CleanupStack::PopAndDestroy();
+            itest(err == KErrNone);
+            CleanupStack::PopAndDestroy(); // infoArray, results in a call to CleanupEComArray
+            break;
+
+        }
+
+        case EConfigParams:
+        {
+			RDebug::Print(_L("EConfigParams starting\n"));
+
+			_LIT( KTrueFalseOpt, "True,False" );
+			_LIT( KFalseOpt, "False" );
+			_LIT( KTrueOpt, "True" );
+
+            TInt err;
+            COptionConfig * param = NULL;
+		    TInt paramsCount = formatter->GetNumberConfigParametersL(); //it should be non leaving call
+            itest(paramsCount == formatter->iConfigList.Count());
+
+            TRAP(err, param = formatter->GetConfigParameterL(0));
+            itest(param->Index() == CDexcFormatter::EDumpStack);
+			itest(param->Uid() == KDEXCFormatterUid );
+            itest(param->Source() == COptionConfig::EFormatterPlugin);
+            itest(param->Type() == COptionConfig::ETBool);
+            itest(param->Options() == KTrueFalseOpt);
+            itest(param->ValueAsBool() == 1);
+			param = NULL;
+
+            TRAP(err, param = formatter->GetConfigParameterL(1));
+            itest(param->Index() == CDexcFormatter::EAsciiStack);
+			itest(param->Uid() == KDEXCFormatterUid );
+            itest(param->Source() == COptionConfig::EFormatterPlugin);
+            itest(param->Type() == COptionConfig::ETBool);
+            itest(param->Options() == KTrueFalseOpt);
+            itest(param->ValueAsBool() == 0);
+			param = NULL;
+
+			RDebug::Printf("->TRAP(err, param = formatter->GetConfigParameterL(paramsCount))\n");
+            TRAP(err, param = formatter->GetConfigParameterL(paramsCount));
+            itest(err == KErrBadHandle);
+			param = NULL;
+
+			RDebug::Printf("formatter->SetConfigParameterL( 0, (TInt)EFalse, KFalseOpt );\n");
+		    TRAP(err, formatter->SetConfigParameterL( 0, (TInt)EFalse, KFalseOpt ));
+			itest(err == KErrNone);
+			itest(formatter->iConfigList[0]->ValueAsBool() == EFalse);
+			TRAP(err, param = formatter->GetConfigParameterL(0));
+            itest(formatter->iConfigList[0]->ValueAsBool() == EFalse);
+            itest(param->ValueAsDesc() == KFalseOpt);
+
+			RDebug::Printf("formatter->SetConfigParameterL( 0, (TInt)ETrue, KTrueOpt );\n");
+		    TRAP(err, formatter->SetConfigParameterL( 0, (TInt)ETrue, KNullDesC ));
+			itest(err == KErrNone);
+			TRAP(err, param = formatter->GetConfigParameterL(0));
+			itest(formatter->iConfigList[0]->ValueAsBool());
+            itest(param->ValueAsDesc() == KTrueOpt);
+            
+			RDebug::Print(_L("EConfigParams finished\n"));
+
+            break;
+        }
+
+        case EDumpLog:
+        {           
+			RDebug::Print(_L("EDumpLog starting.... \n"));
+            //            0123456789012345678901234567890123456789012345678901234567890123456789012345
+            _LIT8(KLine, "----------------------------------------------------------------------------");
+            //                  0 12345678901234567890 1 23456789012345   6 78901234567890 1 2345678901234?
+            _LIT8(KLogDump, "%S\r\nEKA2 USER CRASH LOG\r\nThread Name: %S\r\nThread ID: %u\r\nUser Stack %08X-%08X\r\n");
+            TBuf8<65+76+KMaxName+11+16> reference; //line, thread name, id and 2x 8-digits
+
+            //add newLC
+            CThreadInfo *thread = CThreadInfo::NewL(KCrashTid,
+                                                    KCrashThreadName,
+                                                    KCrashPid,
+                                                    KCrashThreadPriority,
+                                                    KCrashSvcStackPtr,
+                                                    KCrashSvcStackAddr,
+                                                    KCrashSvcStackSize,
+                                                    KCrashUsrStackAddr,
+                                                    KCrashUsrStackSize);
+            
+			RDebug::Print(_L("  -> writer->OpenL(_L(\"\"), handle)\n"));
+            writer->OpenL(_L("")); //clear writer buffer
+            formatter->DumpLogL(*thread);
+            delete thread;
+            itest(writer->iData != KLogDump());
+            reference.Format(KLogDump, &KLine, &KCrashThreadName8, KCrashTid, KCrashUsrStackAddr, KCrashUsrStackAddr + KCrashUsrStackSize);
+            itest(writer->iData == reference);
+			RDebug::Print(_L("EDumpLog finished\n"));
+            break;
+        }
+
+        case EDumpPanicInfo:
+        {
+			RDebug::Print(_L("EDumpPanicInfo starting.... \n"));
+            //                 0123456  7 8 9 0
+			_LIT8(KPanicDump, "Panic: %S-%d\r\n");
+            RBuf8 reference; 
+            reference.CreateL(KPanicDump().Length() + 11 + KMaxExitCategoryName);
+            CleanupClosePushL(reference);
+
+            TCrashInfo crash;
+            crash.iReason = KCrashReason;
+            crash.iCategory = KCrashCategory;
+
+            writer->OpenL(_L("")); //clear writer buffer
+            formatter->DumpPanicInfoL(crash);
+            itest(writer->iData != KPanicDump());
+
+    		reference.Format(KPanicDump, &KCrashCategory8, KCrashReason);
+
+            itest(writer->iData == reference);
+
+            CleanupStack::PopAndDestroy(); //reference
+			RDebug::Print(_L("EDumpPanicInfo finished\n"));
+            break;
+        }
+
+        case EDumpExcInfo:
+        {
+			RDebug::Print(_L("EDumpExcInfo starting.... \n"));
+
+            _LIT8(KExcDump, "\r\nUNHANDLED EXCEPTION:\r\ncode=%d PC=%08x FAR=%08x FSR=%08x\r\nR13svc=%08x R14svc=%08x SPSRsvc=%08x\r\n");
+            //     012345 6 7890123456789012345678901234567890123 4 5
+            RBuf8 reference;
+            reference.CreateL(KExcDump().Length() + 11 + 6*4);
+            CleanupClosePushL(reference);
+
+            TCrashInfo crash;
+			crash.iType = TCrashInfo::ECrashException;
+			crash.iContext.iExcCode = KCrashExcCode;
+
+            crash.iContext.iFaultAddress = KCrashFaultAddress;
+            crash.iContext.iFaultStatus = KCrashFaultStatus;
+
+			crash.iContext.iR15 = KRegValue32 + KCrashTid;
+			crash.iContext.iR13Svc = crash.iContext.iR15 + 1;
+			crash.iContext.iR14Svc = crash.iContext.iR15 + 2;
+			crash.iContext.iSpsrSvc = crash.iContext.iR15 + 3;
+
+            writer->Open(_L("")); //clear writer buffer
+            formatter->DumpExcInfoL(crash);
+
+			RDebug::Print( _L("-> itest(writer->iData != KExcDump())\n") );
+            itest(writer->iData != KExcDump());
+
+            TInt32 code = KCrashExcCode;
+            TInt32 pc = KRegValue32 + KCrashTid; //index of r15
+            TInt32 far = KCrashFaultAddress; 
+            TInt32 fsr = KCrashFaultStatus;
+            TInt32 r13svc = KRegValue32 + KCrashTid + 1; //index of r13svc
+            TInt32 r14svc = KRegValue32 + KCrashTid + 2; //index of r14svc
+            TInt32 spsr = KRegValue32 + KCrashTid + 3; //index of spsr 
+
+            reference.Format(KExcDump, code, pc, far, fsr, r13svc, r14svc, spsr);
+
+			/*
+			RBuf8 referencePrint;
+		    referencePrint.CreateL(256);
+			referencePrint.Copy( reference );
+			char *tonp = (char*) referencePrint.PtrZ();
+			LOG_MSG2("  KExcDump=%s\n", tonp);
+			referencePrint.Close();
+			writer->Print();
+			*/
+			RDebug::Print( _L("-> itest(writer->iData == reference)\n") );
+			itest(writer->iData == reference);
+
+            CleanupStack::PopAndDestroy(); //reference
+			RDebug::Print(_L("EDumpExcInfo finished\n"));
+
+            break;
+        }
+
+        case EDumpRegisters:
+        {
+			RDebug::Print(_L("EDumpRegisters starting.... \n"));
+
+            _LIT8(KCpsrDump, "\r\nUSER REGISTERS:\r\nCPSR=%08x\r\n");
+            _LIT8(KRegsDump, "r%02d=%08x %08x %08x %08x\r\n");
+            RBuf8 reference;
+            reference.CreateL(KCpsrDump().Length() + 4 + KCoreRegsCount * (KRegsDump().Length() + 4*4));
+            CleanupClosePushL(reference);
+
+            writer->Open(_L("")); //clear writer buffer
+            TRAP(err, formatter->DumpRegistersL(KCrashTid));
+            itest(err == KErrNone);
+            itest(writer->iData != KRegsDump());
+
+            TInt32 cpsr = KRegValue32 + KCrashTid + 16; //index of cpsr 
+
+            reference.Format(KCpsrDump, cpsr); 
+            TBuf8<41> line;
+            #define REG_VAL(i) ( KRegValue32 + KCrashTid + i )
+            for(TInt i = 0; i < KCoreRegsCount; i+=4)
+            {
+                TInt reg0 = REG_VAL(i);
+                TInt reg1 = REG_VAL(i+1);
+                TInt reg2 = REG_VAL(i+2);
+                TInt reg3 = REG_VAL(i+3);
+                line.Format(KRegsDump, i, reg0, reg1, reg2, reg3);
+                reference.Append(line);
+            }
+            #undef REG_VAL
+            itest(writer->iData == reference);
+            CleanupStack::PopAndDestroy(); //reference
+			RDebug::Print(_L("EDumpRegisters finished\n"));
+
+            break;
+        }
+
+        case EDumpCodeSegs:
+        {
+			RDebug::Print(_L("EDumpCodeSegs starting.... \n"));
+
+            _LIT8(KSegsLine, "%08X-%08X %S\r\n");
+            RBuf8 line;
+            CleanupClosePushL(line);
+            line.CreateL(KSegsLine().Length() + 2*4 + KMaxFileName);
+            //               0123456789012345679012
+	        _LIT8(KSegsDump, "\r\nCODE SEGMENTS:\r\n");
+            RBuf8 reference;
+            CleanupClosePushL(reference);
+            reference.CreateL(KSegsDump().Length() + KCodeSegsCount * (line.MaxLength()) + 76);
+
+            writer->Open(_L("")); //clear writer buffer
+            formatter->DumpCodeSegsL(KCrashPid);
+			//writer->Print();
+
+            itest(writer->iData != KSegsDump());
+			RDebug::Print( _L(" writer->iData.Length() = %d\n"), writer->iData.Length() );
+
+            reference = KSegsDump();
+            TUint base;
+            TUint size;
+
+			// See CTestCrashDataSource::GetCodeSegmentsL()
+            
+			base = KCrashCodeRunAddr + KCrashPid;
+			size= KCrashCodeSize + KCrashPid;
+            line.Format(KSegsLine, base, base + size, &KCrashProcessName8);
+            reference.Append(line);
+
+			base = KCrashCodeRunAddr + KCrashPid + 1;
+			size= KCrashCodeSize + KCrashPid + 1;
+            line.Format(KSegsLine, base, base + size, &KLibName1_8);
+            reference.Append(line);
+
+			base = KCrashCodeRunAddr + KCrashPid + 2;
+			size= KCrashCodeSize + KCrashPid + 2;
+            line.Format(KSegsLine, base, base + size, &KLibName2_8);
+            reference.Append(line);
+           
+            reference.Append(_L8("\r\n"));
+
+			/*
+			RBuf8 referencePrint;
+		    referencePrint.CreateL(256);
+			referencePrint.Copy( reference );
+			char *tonp = (char*) referencePrint.PtrZ();
+			LOG_MSG2("  KCodeSeg=%s\n", tonp);
+			referencePrint.Close();
+			writer->Print();
+			*/
+
+			itest(writer->iData == reference);
+            CleanupStack::PopAndDestroy(2);
+			RDebug::Print(_L("EDumpCodeSegs finished\n"));
+            break;
+        }
+
+        case EDumpStack:
+        {
+			RDebug::Print(_L("EDumpStack starting.... \n"));
+			_LIT( KFalseOpt, "False" );
+
+            CThreadInfo *thread = CThreadInfo::NewL(KCrashTid,
+                                                    KCrashThreadName,
+                                                    KCrashPid,
+                                                    KCrashThreadPriority,
+                                                    KCrashSvcStackPtr,
+                                                    KCrashSvcStackAddr,
+                                                    KCrashSvcStackSize,
+                                                    KCrashUsrStackAddr,
+                                                    KCrashUsrStackSize);
+
+			CleanupStack::PushL(thread);
+
+            RBuf8 stack;
+            stack.CreateL(KCrashUsrStackSize*5);
+            CleanupClosePushL(stack);
+            
+            writer->Open(_L("")); //clear writer buffer
+		    formatter->SetConfigParameterL( 1, (TInt32)EFalse, KFalseOpt ); //binary dump
+            formatter->DumpStackL(KCrashTid, *thread); 
+
+            for( TInt i = 0; i < KCrashUsrStackSize; i++ )
+		    {
+                stack.Append((TUint8*)&i, 1);
+            }
+
+			RDebug::Printf("itest(writer->iData == stack);");
+            itest(writer->iData == stack);
+            itest(writer->iData != _L8(""));
+            stack.Zero();
+
+            for(TInt i = 0; i < KCrashUsrStackSize; i+=16)
+            {
+                stack.AppendNumFixedWidth(KCrashUsrStackAddr + i, EHex, 8);
+                stack.Append(_L8(": "));
+                for(TInt j = 0; j < 16; ++j)
+                {
+                    stack.AppendNumFixedWidth(i+j, EHex, 2); 
+                    stack.Append(' ');
+                }
+                for(TInt j = 0; j < 16; ++j)
+                {
+                    TInt c = i+j;
+                    if(c < 0x20 || c >= 0x7f) //something writable
+						c = 0x2e; //.
+                    stack.Append(TChar(c));
+                }
+                stack.AppendFormat(_L8("\r\n"));
+            }
+
+            writer->OpenL(_L("")); //clear writer buffer
+			RDebug::Printf("formatter->SetConfigParameterL( 1, (TInt)ETrue, KNullDesC );");
+		    formatter->SetConfigParameterL( 1, (TInt)ETrue, KNullDesC ); //ascii dump
+
+			RDebug::Printf("formatter->DumpStackL(KCrashTid, *thread);");
+            formatter->DumpStackL(KCrashTid, *thread); 
+
+			RDebug::Printf("itest(writer->iData == stack);");
+            itest(writer->iData == stack);
+            itest(writer->iData != _L8(""));
+            CleanupStack::PopAndDestroy();
+			CleanupStack::PopAndDestroy(thread);
+			RDebug::Print(_L("EDumpStack finished\n"));
+            break;
+        }
+        
+        default:
+            break;
+    }
+    RDebug::Print(_L("<- TestSuite(%d)\n"), aSuite);
+}
+
+void RunTestsL()
+{
+    RDebug::Print(_L("-> RunTestsL()\n"));
+
+    CDexcFormatterTest::TSuite suite[] = {
+                                         CDexcFormatterTest::ENone,
+                                         CDexcFormatterTest::EConfigData,
+                                         CDexcFormatterTest::EFindImplementation,
+                                         CDexcFormatterTest::EConfigParams,
+                                         CDexcFormatterTest::EGetDescription,
+                                         CDexcFormatterTest::EDumpLog,
+                                         CDexcFormatterTest::EDumpPanicInfo,
+                                         CDexcFormatterTest::EDumpExcInfo,
+                                         CDexcFormatterTest::EDumpRegisters,
+										 CDexcFormatterTest::EDumpCodeSegs,
+										 CDexcFormatterTest::EDumpStack,
+                                         CDexcFormatterTest::ECrash
+                                         };
+
+    RTest rtest(KTestTitle);
+    rtest.Title(); 
+    rtest.Start(_L(""));
+    CDexcFormatterTest::TSuite *test = suite; 
+
+    while(*test != CDexcFormatterTest::ECrash)
+    {
+        CDexcFormatterTest *itester = CDexcFormatterTest::NewLC(rtest);
+        itester->TestSuiteL(*test++);
+        CleanupStack::PopAndDestroy();
+    }
+
+    rtest.End();
+    rtest.Close();
+    RDebug::Print(_L("<- RunTestsL()\n"));
+}
+
+TInt E32Main()
+{
+    RDebug::Print(_L("-> E32Main()\n"));
+	__UHEAP_MARK;
+	CTrapCleanup* cleanup = CTrapCleanup::New();
+    __ASSERT_ALWAYS(cleanup, User::Panic(_L("D_EXC_TEST-NO_CLEANUP"), KErrNoMemory));
+
+    TRAPD(err, RunTestsL());
+	__ASSERT_ALWAYS(!err, User::Panic(_L("D_EXC_TEST-RunTestsL trapped with error: "), err));
+
+	delete cleanup;
+	__UHEAP_MARKEND;
+    RDebug::Print(_L("<- E32Main()\n"));
+    return err;
+}
+