void CApaAppStart::DoStartAppL(const TDesC &aFileName, const TDesC& aArgs, TBool aViewLess, TBool aStartInBackground, TThreadId& aThreadId, TRequestStatus* aRequestStatusForRendezvous) { // Create an 8-bit variant of aArgs RBuf writableArgs; writableArgs.CreateL(aArgs); CleanupClosePushL(writableArgs); TPtr8 args8 = writableArgs.Collapse(); CApaCommandLine* const cmdLine = CApaCommandLine::NewLC(); SetupCommandLineL(*cmdLine, aFileName, args8, aViewLess, aStartInBackground) ; User::LeaveIfError(iApaLsSession.StartApp(*cmdLine, aThreadId, aRequestStatusForRendezvous)); CleanupStack::PopAndDestroy(cmdLine); CleanupStack::PopAndDestroy(&writableArgs); }
/** * Read command line parameters and control the launching of targets. * Create global launch semaphore KLaunchSemaphoreName */ void MainL() { TInt numApps = KNumApps; TInt numLaunches = KNumLaunches; TInt launchControl = 0; TInt argc = User::CommandLineLength(); HBufC* commandLine = NULL; RDebug::Printf( ">Launcher Process() argc=%d", argc ); if( argc ) { commandLine = HBufC::NewLC(argc); TPtr commandLineBuffer = commandLine->Des(); User::CommandLine(commandLineBuffer); RBuf printCommandLine; CleanupClosePushL( printCommandLine ); printCommandLine.CreateL( commandLine->Des().Length() ); printCommandLine.Copy( commandLine->Des() ); printCommandLine.Collapse(); RDebug::Printf( ">command line = %S", &printCommandLine ); CleanupStack::PopAndDestroy( &printCommandLine ); // 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( numApps ); RDebug::Printf("parsed numApps as %d", numApps); break; case 'm': lex.Val( numLaunches ); RDebug::Printf("parsed numLaunches as %d", numLaunches ); break; case 'o': lex.Val( launchControl ); RDebug::Printf("parsed launchControl as %d", launchControl); break; default: // unknown argument ignore it break; }//switch }// if + }//while }//if argc RSemaphore launchSemaphore; TInt ret = KErrNone; CleanupClosePushL( launchSemaphore ); ret = launchSemaphore.CreateGlobal( KLaunchSemaphoreName, 0 ); RDebug::Printf( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret); User::LeaveIfError( ret ); ret = launchSemaphore.OpenGlobal( KLaunchSemaphoreName ); RDebug::Printf( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret); User::LeaveIfError( ret ); //Only now indicate to the launcher that we have fully started, so they can find and open the semaphore RProcess::Rendezvous(KErrNone); //Now launch the requested number of apps for the requested number of launches for( ; numLaunches > 0; numLaunches-- ) { for( TInt launchIndex = numApps; launchIndex > 0; launchIndex-- ) { RDebug::Printf( ">Target Launcher: Semaphore wait app %d, launch %d", launchIndex, numLaunches ); launchSemaphore.Wait(); RBuf targetName; CleanupClosePushL( targetName ); RDebug::Printf( ">Target Launcher: targetName.Create %d, launch %d", launchIndex, numLaunches ); targetName.Create( KTargetExe().Length() + 2 ); if( launchControl == 1 ) { // Reverse the order of the apps launched by reversing the index in the name RDebug::Printf( ">Target Launcher: targetName.Format %d, launch %d", numApps - launchIndex + 1, numLaunches ); targetName.Format( KTargetExe(), numApps - launchIndex + 1 ); } else { RDebug::Printf( ">Target Launcher: targetName.Format %d, launch %d", launchIndex, numLaunches ); targetName.Format( KTargetExe(), launchIndex ); } RProcess aProc; CleanupClosePushL( aProc ); RDebug::Printf( ">Target Launcher: LaunchProcess %d, launch %d", launchIndex, numLaunches ); RDebug::Printf( ">LaunchProcess %lS", &targetName ); TPtr cmdLinePtr( commandLine->Des() ); ret = LaunchProcess( aProc, targetName, cmdLinePtr ); CleanupStack::PopAndDestroy( &aProc ); RDebug::Printf( "<Target Launcher: LaunchProcess returned %d", ret ); CleanupStack::PopAndDestroy( &targetName ); User::LeaveIfError( ret ); //By now the add proc event should have been delivered to the //test app agent. } } launchSemaphore.Wait( 500000 ); CleanupStack::PopAndDestroy( &launchSemaphore ); if( commandLine ) CleanupStack::PopAndDestroy( commandLine ); }
/** * Read command line parameters and control the launching of the agents. */ void MainL() { LOG_MSG( "ENTER: t_multi_agent_launcher MainL()"); TInt ret = KErrNone; TInt numAgents = KNumAgents; TInt numTargets = KNumTargets; TInt numTestRuns = KNumTestRuns; TInt argc = User::CommandLineLength(); HBufC* commandLine = NULL; LOG_MSG2("t_multi_agent_launcher: MainL(): argc=%d", argc); if(argc) { commandLine = HBufC::NewLC(argc); TPtr commandLineBuffer = commandLine->Des(); User::CommandLine(commandLineBuffer); RBuf printCommandLine; CleanupClosePushL( printCommandLine ); printCommandLine.CreateL( commandLine->Des().Length() ); printCommandLine.Copy( commandLine->Des() ); printCommandLine.Collapse(); LOG_MSG2("t_multi_agent_launcher: command line = %S", &printCommandLine); CleanupStack::PopAndDestroy( &printCommandLine ); // create a lexer and read through the command line TLex lex(*commandLine); while (!lex.Eos()) { // only look for options with first character '-' if (lex.Get() == '-') { TChar arg = lex.Get(); switch ( arg ) { case 'n': lex.Val( numAgents ); LOG_MSG2("t_multi_agent_launcher: parsed numAgents as %d", numAgents); break; case 'm': lex.Val( numTargets ); LOG_MSG2("t_multi_agent_launcher: parsed numTargets as %d", numTargets); break; case 't': lex.Val( numTestRuns ); LOG_MSG2("t_multi_agent_launcher: parsed numTestRuns as %d", numTestRuns); break; default: LOG_MSG("t_multi_agent_launcher: unknown argument ignoring it"); break; } } } } // Note: below is a workaround to overcome an issue with RTest server crashing // when writing to the windows console from different agents (on different CPUs // at the same time). To overcome this we get signaled by the agents when they have // completed their tests so that we can do a RTest complete RSemaphore launchSemaphore; CleanupClosePushL(launchSemaphore); ret = launchSemaphore.CreateGlobal(KLaunchSemaphoreName, 0); LOG_MSG2( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret); User::LeaveIfError( ret ); ret = launchSemaphore.OpenGlobal(KLaunchSemaphoreName); LOG_MSG2( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret); User::LeaveIfError( ret ); //Now launch the requested number of apps for the requested number of test runs for( TInt j = 0; j < numTestRuns; j++ ) { for( TInt i = 0; i < numAgents; i++ ) { RBuf targetName; targetName.CleanupClosePushL(); targetName.CreateL(KAgentExe()); RProcess aProc; CleanupClosePushL(aProc); RBuf launcherOptions; CleanupClosePushL(launcherOptions); const TInt additionalWords = 2; launcherOptions.CreateL( KAgentOptions().Length() + additionalWords ); // Apply offset: launcherOptions.Format( .., .., i * numTargets, ..) // workaround to ensure we have the same binary for multiple agents. // e.g. So if offset = 0, agent attaches to app1, app2, app3, app4, app5 // if offset = 5, agent attached to app6, app7, app8, app9, app10 etc. // Note: apps need to be in rom otherwise the agent will fail on an assert // (with KErrNotFound) launcherOptions.Format( KAgentOptions(), (TUint)numTargets, i * numTargets, 0); ret = LaunchProcess( aProc, targetName, launcherOptions ); CleanupStack::PopAndDestroy(3,&targetName); User::LeaveIfError(ret); } } // Wait for all agents to do their testing before checking the semaphore User::After(12000000); LOG_MSG( ">Target Launcher: Semaphore wait"); for (TInt i = 0; i < numAgents; i ++) { //We need this delay just in case an agent crashes and never signals the sem ret = launchSemaphore.Wait(100000); if( ret != KErrNone ) { LOG_MSG3("launchSemaphore.Wait ret %d for agent %d", ret, i); break; } } LOG_MSG2( "testing for Semaphore ret %d", ret); // We only want to have one RTest instance at any one time since otherwise RTest can panic RTest test(_L("T_MULTI_AGENT_LAUNCHER")); test.Start(_L("t_multi_agent_launcher Check for agents finishing correctly")); test(ret == KErrNone); test.End(); test.Close(); CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore if( commandLine ) CleanupStack::PopAndDestroy(commandLine); LOG_MSG("EXIT: t_multi_agent_launcher MainL()"); }
TInt CMultiTargetAgent::LaunchTargetsInOrderL() { RDebug::Printf( "CMultiTargetAgent::LaunchTargetsInOrderL" ); RBuf launcher; CleanupClosePushL( launcher ); launcher.CreateL( KLauncherExe() ); RBuf launcherOptions; CleanupClosePushL( launcherOptions ); launcherOptions.CreateL( KTargetOptions().Length() + 2 ); launcherOptions.Format( KTargetOptions(), (TUint)ENormalExit ); RDebug::Printf( ">LaunchProcess()" ); RProcess launcherProc; CleanupClosePushL( launcherProc ); TInt ret = LaunchProcess( launcherProc, launcher, launcherOptions ); RDebug::Printf( "<LaunchProcess() ret %d", ret ); CleanupStack::PopAndDestroy( &launcherProc ); // launcherProc CleanupStack::PopAndDestroy( &launcherOptions ); // launcherOptions CleanupStack::PopAndDestroy( &launcher ); //launcher test( ret == KErrNone ); RSemaphore launchSemaphore; CleanupClosePushL( launchSemaphore ); TFindSemaphore launchSemFinder( KLaunchSemaphoreNameSearchString ); TFullName semaphoreResult; ret = launchSemFinder.Next(semaphoreResult); RDebug::Printf( "> Find Launch Semaphote.Next ret=%d, %lS", ret, &semaphoreResult ); test( ret == KErrNone ); ret = launchSemaphore.OpenGlobal( semaphoreResult ); RDebug::Printf( "> OpenGlobal semaphore ret=%d", ret ); test( ret == KErrNone ); TBool thisLaunchCompleted; test.Next(_L("LaunchTargetsInOrderL\n")); for( TInt numLaunches = KNumLaunches; numLaunches > 0; numLaunches-- ) { for( TInt numApps = KNumApps; numApps > 0; numApps-- ) { thisLaunchCompleted = EFalse; // This will trigger the launcher app to launch the next target RDebug::Printf( " >Semaphore.Signal app=%d, launch=%d", numApps, numLaunches); launchSemaphore.Signal(); RBuf8 tgt8Name; CleanupClosePushL( tgt8Name ); RBuf tgtCollapseName; CleanupClosePushL( tgtCollapseName ); tgtCollapseName.CreateL( iTargets[numApps-1] ); tgt8Name.CreateL( tgtCollapseName.Collapse() ); while( ! thisLaunchCompleted ) { RDebug::Printf( ">GetEvent app %d for %S", numApps, &tgt8Name ); iServSession.GetEvent( iTargets[numApps-1], iStatus, iEventPtr ); // Wait for the target to get started. RDebug::Printf( " >Wait for event from target app=%d, launch=%d\n", numApps, numLaunches); User::WaitForRequest( iStatus ); RDebug::Printf( " <Wait for request returned with status %d", iStatus.Int() ); test( iStatus==KErrNone ); RDebug::Printf( " > Got iEventType =%d, app=%d", iEventInfo.iEventType, numApps ); switch( iEventInfo.iEventType ) { case EEventsAddProcess: { RDebug::Printf( "Got EEventsAddProcess" ); TPtrC8 exeNamePtr8( iEventInfo.iAddProcessInfo.iFileName, iEventInfo.iAddProcessInfo.iFileNameLength ); RBuf8 exeName8; CleanupClosePushL( exeName8 ); exeName8.CreateL( exeNamePtr8 ); RDebug::Printf( " from event: exeName8=%S", &exeName8 ); CleanupStack::PopAndDestroy( &exeName8 ); RBuf8 compareName8; CleanupClosePushL( compareName8 ); compareName8.CreateL( KTargetExeName().Length() + 10 ); compareName8.Format( KTargetExeName(), numApps ); RDebug::Printf( " comparing to: compareName8=%S", &compareName8 ); test( compareName8.CompareC( exeNamePtr8 ) == 0 ); CleanupStack::PopAndDestroy( &compareName8 ); RDebug::Printf( "Testing if event process id is valid" ); test( iEventInfo.iProcessIdValid ); RDebug::Printf( "Got iEventInfo.iProcessId=%d", I64LOW( iEventInfo.iProcessId ) ); RProcess targetProc; ret = targetProc.Open( TProcessId( iEventInfo.iProcessId ) ); RDebug::Printf( "RProcess open ret=%d",ret ); targetProc.Close(); test( ret == KErrNone ); break; }//EEventsAddProcess case EEventsStartThread: { RDebug::Printf( "Got EEventsStartThread" ); TPtrC8 exeNamePtr8( iEventInfo.iStartThreadInfo.iFileName, iEventInfo.iStartThreadInfo.iFileNameLength ); RBuf8 exe8Name; CleanupClosePushL( exe8Name ); exe8Name.CreateL( exeNamePtr8 ); RDebug::Printf( " from event: exeName8=%S", &exe8Name ); CleanupStack::PopAndDestroy( &exe8Name ); test( tgt8Name.CompareC( exeNamePtr8 ) == 0 ); RDebug::Printf( "Testing if event process id is valid" ); test( iEventInfo.iProcessIdValid ); RDebug::Printf( "Got iEventInfo.iProcessId=%d", I64LOW( iEventInfo.iProcessId ) ); RDebug::Printf( "Testing if event thread id is valid" ); test( iEventInfo.iThreadIdValid ); RDebug::Printf( "Got iEventInfo.iThreadId=%d", I64LOW( iEventInfo.iThreadId ) ); RThread targetThread; CleanupClosePushL( targetThread ); ret = targetThread.Open( TThreadId( iEventInfo.iThreadId ) ); RDebug::Printf( "RThread open ret=%d", ret ); test( ret == KErrNone ); test( iEventInfo.iThreadId == targetThread.Id() ); RDebug::Printf( "Resuming thread for app=%d, id=%d", numApps, I64LOW( targetThread.Id() )); ret = iServSession.ResumeThread( iEventInfo.iThreadId ); CleanupStack::PopAndDestroy( &targetThread ); test( ret == KErrNone ); ret = iServSession.ResumeThread( iEventInfo.iThreadId ); break; }//case EEventsStartThread case ( EEventsRemoveProcess ): { RDebug::Printf( "*** Got EEventsRemoveProcess. app%d has exited. Moving on to next app", numApps ); thisLaunchCompleted = ETrue; break; } default : RDebug::Printf( "Got unknown event" ); test( EFalse ); break; } }//while CleanupStack::PopAndDestroy( &tgtCollapseName ); // tgtCollapseName CleanupStack::PopAndDestroy( &tgt8Name ); // tgt8Name } } launchSemaphore.Signal(); CleanupStack::PopAndDestroy( &launchSemaphore ); // launchSemaphore for( TInt i = iTargets.Count()-1; i>=0; i-- ) { RDebug::Printf( "Closing target %d", i ); iTargets[ i ].Close(); } iTargets.Close(); return KErrNone; }