debugsrv/runmodedebug/tsrc/rm_debug/performance_test/t_rmdebug_performance_test.cpp
changeset 56 aa2539c91954
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/tsrc/rm_debug/performance_test/t_rmdebug_performance_test.cpp	Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,599 @@
+// Copyright (c) 2010 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:
+// Tests performance of run mode debug device component   
+//
+
+#include <e32base.h>
+#include <e32property.h>
+#include <e32test.h>
+#include <e32def.h>
+#include <e32const.h>
+#include <hal.h>
+
+#include "t_rmdebug_performance_test.h"
+#include "t_debug_logging.h"
+#include "t_rmdebug_app.h"
+
+const TVersion securityServerVersion(0,1,1);
+
+_LIT(KTestName, "T_RMDEBUG_PERFORMANCE_TEST");
+
+LOCAL_D RTest test(KTestName);
+
+using namespace Debug;
+
+CRunModeAgent* CRunModeAgent::NewL()
+    {
+    LOG_ENTRY();
+    CRunModeAgent* self = new(ELeave) CRunModeAgent();
+    self->ConstructL();
+    LOG_EXIT();
+    return self;
+    }
+
+void CRunModeAgent::ConstructL()
+    {
+    // ConstructL list does not match destruction list as R-Class member variables are implicitly open.
+    // DebugDriver().Connect() is conditionally set depending on the test case hence not part of this function.
+    LOG_ENTRY();
+    User::LeaveIfError(iIntegerProperty.Attach(RProcess().SecureId(), EPropertyTimeOfCrash, EOwnerThread));
+    LOG_EXIT(); 
+    }
+
+CRunModeAgent::~CRunModeAgent()
+    {
+    LOG_ENTRY();   
+    DebugDriver().Close();
+    iTimeDifs.Close();
+    iIntegerProperty.Close();
+    RProperty::Delete(EPropertyTimeOfCrash);
+    LOG_EXIT(); 
+    }
+
+
+void CRunModeAgent::ClientAppL()
+    {
+    LOG_ENTRY();   
+   
+    if ( ParseCommandLine() == EDisplayHelp )
+        {
+        DisplayUsage();
+        }
+    else
+        {
+        static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
+        RProperty::Define(RProcess().SecureId(), EPropertyTimeOfCrash, RProperty::EInt, KAllowAllPolicy, KAllowAllPolicy);        
+        StartTest();
+        }
+        
+    LOG_EXIT(); 
+    }
+
+TInt CRunModeAgent::GetTimeInMs()
+{
+    return User::NTickCount() * iTickPeriodMs;
+}
+
+void CRunModeAgent::GetStartTime()
+    {    
+    LOG_ENTRY();
+
+    test ( KErrNone == iIntegerProperty.Get(iParams.iCountStart) );    
+    LOG_MSG2("iParams.iCountStart %d", iParams.iCountStart);
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::GetNanoTickPeriod()
+    {
+    LOG_ENTRY();
+    
+    TInt period = 0;
+    User::LeaveIfError(HAL::Get(HALData::ENanoTickPeriod, period));
+    iTickPeriodMs = period / 1000;
+    LOG_MSG("iTickPeriodMs = %d\n", iTickPeriodMs);
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::StartTest()
+    {
+    LOG_ENTRY();
+    
+    GetNanoTickPeriod();
+    
+    if (iParams.iTestType == PerformanceTestParams::EBenchMarkTest)
+        {
+        RunBenchMarkTest();
+        }
+    else 
+        {
+        TestDriverPerformance();
+        }
+    
+    CalculatePerformance();
+    
+    LOG_EXIT();
+    }
+
+// This function allows us to provide a benchmark when comparing the performance with the 
+// old and new APIs using the TestDriverPerformance function below. The two possible 
+// configurations are as follows: 
+// 1. Run t_rmdebug_app with a prefetch abort configuration and measure the time from the 
+// point of crash to the logon request completion.
+// 2. Load the debug-system and then run the above configuration.  
+void CRunModeAgent::RunBenchMarkTest()
+    {
+    LOG_ENTRY();
+    
+    test.Start(_L("RunBenchMarkTest"));
+    
+    RProcess process;
+    TRequestStatus status; 
+    
+    if (iParams.iDriver)
+         {
+         RDebug::Printf("RunBenchMarkTest() - DebugDriver().Connect()");
+         test(KErrNone == DebugDriver().Connect(securityServerVersion));
+         }
+ 
+    LOG_MSG("iParams.iNumOfTestRuns = %d", iParams.iNumOfTestRuns);
+    
+    for ( TUint i = 0; i < iParams.iNumOfTestRuns; i++ )
+        {
+        // Start test application
+        test( KErrNone == LaunchProcessL(process, KRMDebugTestApplication(), KTargetOptions()) );
+               
+        process.Logon(status);
+        User::WaitForRequest(status);
+
+        // Stop timer on logon request completion
+        iParams.iCountEnd = GetTimeInMs();
+        LOG_MSG("iParams.iCountEnd = %d", iParams.iCountEnd);
+        
+        LOG_MSG( "status.Int() = %d " , status.Int() );
+        
+        // prefetch abort should raise a KERN-EXEC 3
+        test(3 == status.Int());
+        
+        process.Close();
+        GetStartTime(); 
+       
+        // NTickCount shouldn't overflow, so no reason why this assertion should fail
+        test(iParams.iCountEnd > iParams.iCountStart);
+        iTimeDifs.Append( iParams.iCountEnd - iParams.iCountStart );
+       }
+    
+    LOG_EXIT();
+    }
+
+// This function can be used to compare the performance with the old (e.g. attachExe) and new 
+// (e.g. attachAll) APIs depending depending on the parameters passed in when running this test.  
+void CRunModeAgent::TestDriverPerformance()
+    {
+    LOG_ENTRY();    
+    test.Start(_L("TestDriverPerformance"));
+   
+    RProcess process;
+    
+    test(KErrNone == DebugDriver().Connect(securityServerVersion));
+    
+    LOG_MSG("iParams.iNumOfTestRuns = %d", iParams.iNumOfTestRuns);
+    for ( TUint i = 0; i < iParams.iNumOfTestRuns; i++ )
+        {
+        ilaunchCompleted = EFalse;
+     
+        Attach();
+        SetEventAction();
+        test(KErrNone == LaunchProcessL(process, KRMDebugTestApplication(), KTargetOptions));
+        
+        LOG_MSG("CRunModeAgent::TestDriverPerformance - process.Logon");
+        
+        while ( !ilaunchCompleted )
+            {
+            LOG_MSG("CRunModeAgent::TestDriverPerformance - DebugDriver().GetEvent");
+       
+            GetEvent();
+       
+            LOG_MSG("CRunModeAgent::TestDriverPerformance - User::WaitForRequest");
+
+            User::WaitForRequest(iStatus);
+            LOG_MSG( "iStatus.Int() = %d " , iStatus.Int() );
+            
+            LOG_MSG("CRunModeAgent::TestDriverPerformance - HandleEvent");
+            HandleEvent(iSEventInfo.iEventInfo);
+            }
+        
+        process.Logon(iStatus);
+        LOG_MSG("CRunModeAgent::TestDriverPerformance - process.Logon, User::WaitForRequest");
+        User::WaitForRequest(iStatus);
+        LOG_MSG( "iStatus.Int() = %d " , iStatus.Int() );
+        
+        // Stop timer on logon request completion as in benchmark performance test
+        iParams.iCountEnd = GetTimeInMs();
+                
+        // prefetch abort should raise a KERN-EXEC 3
+        test(3 == iStatus.Int());
+                    
+        Detach();
+        process.Close();       
+        GetStartTime();
+ 
+        // NTickCount shouldn't overflow, so no reason why this assertion should fail
+        test(iParams.iCountEnd > iParams.iCountStart);
+        iTimeDifs.Append( iParams.iCountEnd - iParams.iCountStart );
+       }
+        
+       LOG_EXIT();
+    }
+
+void CRunModeAgent::CalculatePerformance()
+    {
+    LOG_ENTRY();
+
+    TUint median;
+    TUint arrayCount = iTimeDifs.Count();
+
+    for (TInt i = 0; i < arrayCount; i++)
+         {
+         RDebug::Printf("iTimeDifs[%d] = %d ",i,iTimeDifs[i]);
+         }
+    
+    // Sort in ascending order
+    iTimeDifs.Sort();
+            
+    //If the number of elements is odd, the middle element in the sorted array is the median. 
+    //If the number of elements is even, the median is the average of the two midmost elements.
+    if ( arrayCount%2  != 0 )
+        {
+        median = iTimeDifs[arrayCount/2];
+        }
+    else
+        {
+        median = (iTimeDifs[arrayCount/2] + iTimeDifs[arrayCount/2 -1])/2;
+        }
+    
+    RDebug::Printf("Median time %d ms", median );
+    
+    LOG_EXIT();
+    }
+
+/**
+  Launch a process
+  @param aExeName the executable used to create the process
+  @param aCommandLine the commandline parameters passed to the new process file name of the executable used to create the process
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt CRunModeAgent::LaunchProcessL( RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine )
+    {
+    LOG_ENTRY(); 
+    
+    RBuf launcherOptions;
+    launcherOptions.CleanupClosePushL();
+    const TInt additionalWords = 1; 
+    launcherOptions.CreateL( aCommandLine.Length() + additionalWords );
+    launcherOptions.Format( aCommandLine, iParams.iTestTargetPriority);
+   
+    LOG_DES(_L("launcherOptions %S"), &launcherOptions);
+    
+    TInt err = aProcess.Create( aExeName, launcherOptions );   
+    CleanupStack::PopAndDestroy();
+    
+    // check that there was no error raised
+    if (err != KErrNone)
+        return err;
+    
+    // rendezvous with process
+    TRequestStatus status = KRequestPending;
+    aProcess.Rendezvous(status);
+
+    // start the test target
+    aProcess.Resume();
+    User::WaitForRequest(status);
+  
+    if(KErrNone != status.Int())
+        {
+        aProcess.Kill(KErrNone);
+        }
+     LOG_EXIT(); 
+     return status.Int();
+
+    }
+
+void CRunModeAgent::SetEventAction()
+    {
+    LOG_ENTRY();
+    
+    if (iParams.iTestType == PerformanceTestParams::EAttachExe)
+        {
+        test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsKillThread, EActionContinue));
+             
+        if ( iParams.iEvents )
+            {
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsAddLibrary, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsUserTrace, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsStartThread, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsAddProcess, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsRemoveProcess, EActionContinue));
+            }
+        }
+    else
+        {
+        test(KErrNone == DebugDriver().SetEventAction( EEventsKillThread, EActionContinue));
+             
+        if ( iParams.iEvents )
+            {
+            test(KErrNone == DebugDriver().SetEventAction( EEventsAddLibrary, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( EEventsUserTrace, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( EEventsStartThread, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( EEventsAddProcess, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( EEventsRemoveProcess, EActionContinue));
+            }
+        }
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::Attach()
+    {
+    LOG_ENTRY();
+    
+    if( iParams.iTestType == PerformanceTestParams::EAttachExe ) 
+        {
+        // Attach to process non-passively
+        test(KErrNone == DebugDriver().AttachExecutable( KRMDebugTestApplication(), EFalse));
+        LOG_MSG("DebugDriver().AttachExecutable");
+        }
+    else 
+        {
+        // Attach to all the processes on the system
+        test(KErrNone == DebugDriver().AttachAll());
+        LOG_MSG("DebugDriver().AttachAll()");
+        }
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::GetEvent()
+    {
+    LOG_ENTRY();
+
+    if( iParams.iTestType == PerformanceTestParams::EAttachExe ) 
+        {
+        DebugDriver().GetEvent( KRMDebugTestApplication(), iStatus, iSEventInfo.iEventInfoBuf );
+        }
+    else
+        {
+        DebugDriver().GetEvent( iStatus, iSEventInfo.iEventInfoBuf );
+        }
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::Detach()
+    {
+    LOG_ENTRY();
+    
+    if( iParams.iTestType == PerformanceTestParams::EAttachExe )
+        {
+        test (KErrNone == DebugDriver().DetachExecutable(KRMDebugTestApplication()));
+        }
+    else
+        {
+        test(KErrNone == DebugDriver().DetachAll());
+        }
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::HandleEvent(TEventInfo& aEventInfo)
+    {
+    LOG_ENTRY(); 
+
+    switch ( aEventInfo.iEventType )
+        {
+        case EEventsAddProcess:
+            {
+            LOG_MSG(">>> EEventsAddProcess");                        
+            break;
+            }
+    
+        case EEventsStartThread:
+            {
+            LOG_MSG(">>> EEventsStartThread");                
+            break;                    
+            }                       
+
+        case EEventsUserTrace:
+            {
+            LOG_MSG(">>> EEventsUserTrace");  
+            break;
+            }
+
+        case EEventsRemoveProcess:
+            {
+            LOG_MSG(">>> EEventsRemoveProcess");                        
+            break;
+            }
+    
+        case EEventsKillThread:
+            {
+            LOG_MSG(">>> EEventsKillThread");   
+            ilaunchCompleted = ETrue;          
+            break;
+            }
+            
+        default:   
+            {
+            LOG_MSG( ">>> Unknown event ");
+            break;
+            }   
+        }
+     
+    LOG_EXIT(); 
+    }
+
+void CRunModeAgent::SetDefaultParamValues()
+    {
+    LOG_ENTRY();
+    
+    iParams.iNumOfTestRuns = KNumOfTestRuns;
+    iParams.iTestType = PerformanceTestParams::EBenchMarkTest;
+    iParams.iTestTargetPriority = 0;
+    iParams.iEvents = 0;
+    iParams.iDriver = 0;
+    
+    LOG_EXIT();
+    }
+
+TInt CRunModeAgent::ParseCommandLine()
+    {
+    LOG_ENTRY();
+    
+    TBool ifDisplayHelp = EDontDisplayHelp;
+    SetDefaultParamValues();
+    
+    TInt argc = User::CommandLineLength();
+    LOG_MSG( "Launcher Process() argc=%d", argc );
+
+    if( argc )
+        {
+        HBufC* commandLine = NULL;
+        commandLine = HBufC::NewLC(argc);
+        TPtr commandLineBuffer = commandLine->Des();
+        User::CommandLine(commandLineBuffer);
+       
+        LOG_DES(_L("CommandLine = %S"), &commandLineBuffer);
+        
+        // create a lexer and read through the command line
+        TLex lex(*commandLine);
+        while (!lex.Eos())
+             {
+             // only look for options with first character '-', other switches are for the targets
+             if (lex.Get() == '-')
+                 {
+                 TChar arg = lex.Get();
+                 switch (arg)
+                     {
+                     case 'n':
+                         lex.Val( iParams.iNumOfTestRuns );
+                         LOG_MSG("Number of test runs %d", iParams.iNumOfTestRuns);
+                         break;
+                      case 't':
+                          lex.Val( iParams.iTestType );
+                          LOG_MSG("parsed testType as %d", iParams.iTestType );
+                          break;
+                      case 'p':
+                          lex.Val( iParams.iTestTargetPriority );
+                          LOG_MSG("parsed test target priority as %d", iParams.iTestTargetPriority );
+                          break;
+                      case 'e':
+                          lex.Val( iParams.iEvents );
+                          LOG_MSG("parsed events as %d", iParams.iEvents );
+                          break;
+                      case 'd':
+                          lex.Val( iParams.iDriver );
+                          LOG_MSG("parsed iDriver as %d", iParams.iDriver );
+                          break;
+                       case 'h':
+                          LOG_MSG( "Display help" );
+                          ifDisplayHelp = EDisplayHelp;
+                       default:
+                           LOG_MSG( "Default usage" );
+                           break;             
+                       }
+                  }
+              }
+            CleanupStack::PopAndDestroy(commandLine);
+        }
+    
+    LOG_EXIT();
+    return ifDisplayHelp;   
+    }
+
+void CRunModeAgent::DisplayUsage()
+    {
+    LOG_ENTRY();
+    test.Printf(_L("\nUsage: t_rmdebug_performance_test [options] \nOptions:\n"));
+    
+    test.Printf(_L("\t-t  \t\ttest type\n"));
+    test.Printf(_L("\t\t\t  0 - AttachAll\n"));
+    test.Printf(_L("\t\t\t  1 - AttachExe\n"));
+    test.Printf(_L("\t\t\t  2 - None\n"));
+           
+    test.Printf(_L("\t-n \t\tnumber of iterations\n"));
+    test.Printf(_L("\t-e \t\ttest with events\n"));
+    test.Printf(_L("\t\t\t  0 - No\n"));
+    test.Printf(_L("\t\t\t  1 - Yes\n"));
+    test.Printf(_L("\t-p \t\tpriority of test target thread\n"));
+    
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteVeryLow \n"), EPriorityAbsoluteVeryLow);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteLowNormal \n"), EPriorityAbsoluteLowNormal);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteLow \n"), EPriorityAbsoluteLow);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteBackgroundNormal \n"), EPriorityAbsoluteBackgroundNormal);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteBackground \n"), EPriorityAbsoluteBackground);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteForegroundNormal \n"), EPriorityAbsoluteForegroundNormal);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteForeground \n"), EPriorityAbsoluteForeground);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteHighNormal \n"), EPriorityAbsoluteHighNormal);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteHigh \n"), EPriorityAbsoluteHigh);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime1 \n"), EPriorityAbsoluteRealTime1);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime2 \n"), EPriorityAbsoluteRealTime2);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime3 \n"), EPriorityAbsoluteRealTime3);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime4 \n"), EPriorityAbsoluteRealTime4);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime5 \n"), EPriorityAbsoluteRealTime5);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime6 \n"), EPriorityAbsoluteRealTime6);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime7 \n"), EPriorityAbsoluteRealTime7);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime8 \n"), EPriorityAbsoluteRealTime8);
+    
+    test.Printf(_L("\t-d  \t\tload driver\n"));
+    test.Printf(_L("\t\t\t  0 - No\n"));
+    test.Printf(_L("\t\t\t  1 - Yes\n"));
+        
+    test.Printf(_L("\t-h \t\tdisplay usage information\n\n"));
+    
+    test.Printf(_L("Press any key...\n"));
+    test.Getch();
+    
+    LOG_EXIT();
+    }
+
+GLDEF_C TInt E32Main()
+    {
+    __UHEAP_MARK;
+
+    TInt ret = KErrNone;        
+    CTrapCleanup* trap = CTrapCleanup::New();
+        
+    if (!trap)
+        return KErrNoMemory;
+    
+    test.Start(KTestName);
+       
+    CRunModeAgent *runModeAgent = CRunModeAgent::NewL();
+
+    if (runModeAgent != NULL)
+        {
+        TRAP(ret,runModeAgent->ClientAppL());
+        LOG_MSG( "ClientAppL() returned %d", ret );
+        delete runModeAgent;
+        }
+    
+    test.End();
+    test.Close();
+
+    delete trap;
+    __UHEAP_MARKEND;
+    return ret;
+    }
+