--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/testexecmgmt/ucc/GenericService/TestDriverService/src/CTestDriverService.cpp Mon Mar 08 15:04:18 2010 +0800
@@ -0,0 +1,597 @@
+/*
+* Copyright (c) 2005-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:
+* CTestDriverService.h
+*
+*/
+
+
+
+#include <stdlib.h>
+
+#include "CAThread.h"
+#include "CListeningServer.h"
+#include "CTestDriverService.h"
+#include "CUCCIniFile.h"
+
+// Parameters names
+const char KPlatform[] = { "PLATFORM" };
+const char KBuild[] = { "BUILD" };
+const char KSuite[] = { "SUITE" };
+const char KTransport[] = { "TRANSPORT" };
+const char KLogging[] = { "LOGGING" };
+
+// Ini file names
+const char KTDServiceIni[] = { ".\\TestDriverService.ini" };
+const char KIniSectionName[] = { "TestDriverService" };
+const char KIniPort[] = { "Port" };
+const char KIniExeLocation[] = { "Exe" };
+const char KIniPollInterval[] = { "Poll" };
+
+// TestDriver parameters and flags
+const char KTDConnection[] = { "localhost" };
+const char KDefaultExe[] = { "C:\\apps\\engtools\\testdriver2\\testdriver" };
+const char KTDBuild[] = { " build " };
+const char KTDRun[] = { " run " };
+const char KPlatformFlag[] = { " -p " };
+const char KBuildFlag[] = { " -b " };
+const char KSuiteFlag[] = { " -s " };
+const char KTransportFlag[] = { " -t " };
+const char KLoggingFlag[] = { " -l " };
+const char KSocketFlag[] = { " -f " };
+
+// TCP Port for TestDriver to use to contact the TestDriverService listening socket
+const int KDefaultPort = 3002;
+const int KContinuePollingValue = 1;
+
+// Default polling timeout for the Listening Server
+const int KDefaultPoll = 5; // 5 seconds
+
+// Static values to control the thread(s) execution
+static bool iServerRunning;
+static bool iTestDriverRunning;
+static int iTDStartResult;
+static int iTDCompleteResult;
+static bool iTDContinuePolling;
+static bool iTDRunSetupComplete;
+static char* iRunCommandLine;
+static CAThread* iServer;
+static CAThread* iTestDriverRun;
+static HANDLE iServerMutex;
+static HANDLE iTDRunMutex;
+
+static string iExe;
+static int iPort;
+static int iPollInterval;
+
+CService* Service() { return new CTestDriverService(); }
+
+/*
+ * Constructor
+ */
+CTestDriverService::CTestDriverService()
+ {
+ iServerRunning = false;
+ iTestDriverRunning = false;
+ iTDStartResult = 0;
+ iTDCompleteResult = 0;
+ iTDContinuePolling = false;
+ iTDRunSetupComplete = false;
+ iServer = NULL;
+ iRunCommandLine = NULL;
+ iServerMutex = NULL;
+ iTDRunMutex = NULL;
+ iExe = KDefaultExe;
+ iPort = KDefaultPort;
+ iPollInterval = KDefaultPoll;
+ }
+
+/*
+ * Destructor
+ */
+CTestDriverService::~CTestDriverService()
+ {
+ // Let the Listening Server clean itself up
+ Wait( iServerMutex );
+ if( iServerRunning )
+ {
+ iServerRunning = false;
+ }
+ iServer->WaitForThread( -1 );
+ if( iServer != NULL )
+ {
+ delete iServer;
+ iServer = NULL;
+ }
+ Release( iServerMutex );
+ ReleaseMutex( iServerMutex );
+ CloseHandle( iServerMutex );
+
+ // Clean up the TestDriver thread
+ Wait( iTDRunMutex );
+ if( iTestDriverRunning )
+ {
+ iTestDriverRunning = false;
+ }
+ iTestDriverRun->WaitForThread( -1 );
+ if( iTestDriverRun != NULL )
+ {
+ delete iTestDriverRun;
+ iTestDriverRun = NULL;
+ }
+
+ // Cleanup the shared command line
+ if( iRunCommandLine != NULL )
+ {
+ delete [] iRunCommandLine;
+ iRunCommandLine = NULL;
+ }
+ Release( iTDRunMutex );
+ ReleaseMutex( iTDRunMutex );
+ CloseHandle( iTDRunMutex );
+ }
+
+
+/*
+ * Setup
+ *
+ * Creates the mutex's requires by this service
+ */
+bool CTestDriverService::Setup()
+ {
+ bool ret = false;
+
+ // Read the ini file configuration if available, otherwise default
+ RetrieveConfig();
+
+ // Create the Listening Server and TestDrive run mutex
+ iServerMutex = CreateMutex( NULL, false, NULL );
+ iTDRunMutex = CreateMutex( NULL, false, NULL );
+
+ if( iServerMutex != NULL && iTDRunMutex != NULL )
+ {
+ ret = true;
+ }
+
+ return ret;
+ }
+
+/*
+ * RunCommand
+ *
+ * Extracts the call id and delegates to the required functionality
+ */
+int CTestDriverService::RunCommand( const CCall& aCall )
+ {
+ int ret = ERR_INVALID_CALL;
+ bool callRet = false;
+
+ // Retrieve the call id
+ int callID = -1;
+ callRet = aCall.CallID( callID );
+ if( callRet )
+ {
+ switch( callID )
+ {
+ case 1: // Build and initiate TestDriver (TestExecute) execution
+ {
+ ret = BuildAndRunTestDriver( aCall );
+ }
+ break;
+ case 2: // Retrieve the TestDriver run execution result
+ {
+ ret = RetrieveTestDriverRunResult();
+ }
+ break;
+ default:
+ {
+ ret = ERR_INVALID_CALL;
+ }
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+/*
+ * BuildAndRunTestDriver
+ *
+ * Builds all of the dependancies and starts the execution via TestDriver
+ */
+int CTestDriverService::BuildAndRunTestDriver( const CCall& aCall )
+ {
+ int ret = ERR_NONE;
+
+ // Test to see if the Listening Server is already running
+ // If running, we wait for it exit.
+ Wait( iServerMutex );
+ if( iServerRunning )
+ {
+ Release( iServerMutex );
+ RetrieveTestDriverRunResult();
+ //ret = ERR_TEST_DRIVER_ALREADY_RUNNING;
+ }
+ else
+ {
+ Release( iServerMutex );
+ }
+
+ // Retrieve all the parameters
+
+ // The build command line
+ string buildCommandLine;
+ buildCommandLine += iExe;
+ buildCommandLine += KTDBuild;
+ if( !ret )
+ {
+ ret = AppendCmdLineParams( aCall, buildCommandLine );
+ }
+
+ // The run command line
+ string runCommandLine;
+ runCommandLine += iExe;
+ runCommandLine += KTDRun;
+ if( !ret )
+ {
+ ret = AppendCmdLineParams( aCall, runCommandLine );
+ }
+
+ // Make the TestDriver build call
+ if( !ret )
+ {
+ int tdRet = system( buildCommandLine.c_str() );
+ if( tdRet )
+ {
+ ret = ERR_TEST_DRIVER_BUILD;
+ }
+ }
+
+ if( !ret )
+ {
+ // Append the details for the listening socket
+ runCommandLine += KSocketFlag;
+ runCommandLine += KTDConnection;
+ runCommandLine += ":";
+ char portBuf[20];
+ sprintf( portBuf, "%d", iPort );
+ runCommandLine += portBuf;
+
+ if( iRunCommandLine != NULL )
+ {
+ delete [] iRunCommandLine;
+ iRunCommandLine = NULL;
+ }
+
+ // Setup the command line for the execution thread
+ iRunCommandLine = new char[runCommandLine.length()+1];
+ strcpy( iRunCommandLine, runCommandLine.c_str() );
+ }
+
+ // Start the listening server in its own thread
+ if( !ret )
+ {
+ // Set the server running flag to true
+ iServerRunning = true;
+ // Kick off the Listening Server in its own thread
+ iServer = new CAThread( "CTestDriverService::ListeningServer" );
+ int err = 1;
+ TThreadError terr = iServer->StartThread( (void*)CTestDriverService::ListeningServer, NULL, &err );
+ if( terr != TE_NONE )
+ {
+ delete iServer;
+ iServer = NULL;
+ ret = ERR_TEST_DRIVER_RUN;
+ }
+ }
+
+ // Launch TestDriver in run mode in its own thread
+ if( !ret )
+ {
+ // Set the TestDriver running flag to true
+ iTestDriverRunning = true;
+ // Kick off TestDriver in its own thread
+ iTestDriverRun = new CAThread( "CTestDriverService::TestDriverRun" );
+ int err = 1;
+ TThreadError terr = iTestDriverRun->StartThread( (void*)CTestDriverService::TestDriverRun, NULL, &err );
+ if( terr != TE_NONE )
+ {
+ delete iTestDriverRun;
+ iTestDriverRun = NULL;
+ ret = ERR_TEST_DRIVER_RUN;
+ }
+ }
+
+ // Retrieve the TestDriver run startup result
+ if( !ret )
+ {
+ bool cont = false;
+ while( !cont && iTestDriverRunning )
+ {
+ Sleep( iPollInterval * 1000 );
+ Wait( iServerMutex );
+ iTDRunSetupComplete?cont=true:cont=false;
+ Release( iServerMutex );
+ }
+ Wait( iServerMutex );
+ iTDStartResult>0?ret=0:ret=ERR_TEST_DRIVER_RUN;
+ iTDRunSetupComplete = false;
+ Release( iServerMutex );
+ }
+
+ return ret;
+ }
+
+/*
+ * RetrieveTestDriverRunResult
+ *
+ * Retrieves the result upon the TestDriver run completion
+ */
+int CTestDriverService::RetrieveTestDriverRunResult()
+ {
+ int ret = ERR_NONE;
+
+ Wait( iServerMutex );
+ // Set the continue polling flag
+ iTDContinuePolling = true;
+ Release( iServerMutex );
+
+ // The ListeningServer thread will now issue TestDriver with the command
+ // to complete and cleanup and the return code will be set from the TestDriverRun
+ // thread when the executable completes.
+
+ // Wait for the TestDriverRun thread to complete
+ bool cont = false;
+ while( !cont )
+ {
+ Sleep( iPollInterval * 1000 );
+ Wait( iTDRunMutex );
+ iTestDriverRunning?cont=false:cont=true;
+ Release( iTDRunMutex );
+ }
+
+ // Cleanup the threads as they have now completed
+ Wait( iServerMutex );
+ iServerRunning = false;
+ Release( iServerMutex );
+
+ Wait( iTDRunMutex );
+ iTestDriverRunning = false;
+ Release( iTDRunMutex );
+
+ // Now the TestDriver executable has complete return the
+ // appropriate error code
+ if( iTDCompleteResult < 0 )
+ {
+ ret = ERR_TEST_DRIVER_RUN_COMPLETE;
+ }
+
+ return ret;
+ }
+
+/*
+ * ListeningServer
+ *
+ * Runs the Listening Server
+ * Controlled via the main/TestDriver run thread
+ */
+void CTestDriverService::ListeningServer( void )
+ {
+ // Create a new CListeningServer
+ CListeningServer* server = new CListeningServer();
+ if( server != NULL )
+ {
+ // Open it an wait until TestDriver has connected
+ int err = server->Open( iPort );
+
+ // Continue if TestDriver connected successfully and the server is set to running
+ // Retrieve the TestDriver execution startup result
+ // Loop until told to stop
+ if( !err )
+ {
+ int recvInt = 0;
+ iTDStartResult = 0;
+ bool cont = true;
+ while( cont )
+ {
+ Wait( iServerMutex );
+
+ // Attempt to recieve the TestDriver startup code
+ // This recieve call can timeout and we continue retrying
+ err = server->Recieve( recvInt );
+ if( !err )
+ {
+ // Set the TestDriver run startup result
+ iTDStartResult = recvInt;
+ iTDRunSetupComplete = true;
+ Release( iServerMutex );
+ break;
+ }
+ iServerRunning?cont=true:false;
+ Release( iServerMutex );
+ }
+ }
+
+ // Check to see that TestDriver has returned a run number.
+ // If it hasn't then the startup has failed.
+ if( iTDStartResult > 0 )
+ {
+ // Wait until the continue polling flag has been set
+ bool cont = true;
+ while( !err && cont )
+ {
+ Wait( iServerMutex );
+ if( iTDContinuePolling )
+ {
+ err = server->Send( KContinuePollingValue );
+ // Reset the polling flag
+ iTDContinuePolling = false;
+ Release( iServerMutex );
+ break;
+ }
+ Release( iServerMutex );
+ Sleep( iPollInterval * 1000 );
+ Wait( iServerMutex );
+ iServerRunning?cont=true:cont=false;
+ Release( iServerMutex );
+ }
+ }
+ server->Close();
+ }
+
+ delete server;
+ server = NULL;
+ Wait( iServerMutex );
+ iServerRunning = false;
+ Release( iServerMutex );
+ }
+
+/*
+ * TestDriverRun
+ *
+ * Executes the run command for TestDriver
+ */
+void CTestDriverService::TestDriverRun( void )
+ {
+ Wait( iTDRunMutex );
+ // Launch TestDriver
+ if( iRunCommandLine != NULL )
+ {
+ iTDCompleteResult = system( iRunCommandLine );
+ }
+ else
+ {
+ iTDCompleteResult = -1;
+ }
+
+ // Reset the status to not running
+ iTestDriverRunning = false;
+ Release( iTDRunMutex );
+ }
+
+/*
+ * Wait
+ *
+ * For synchronisation
+ */
+void CTestDriverService::Wait( HANDLE aMutexHandle )
+ {
+ WaitForSingleObject( aMutexHandle, INFINITE );
+ }
+
+/*
+ * Release
+ *
+ * For synchronisation
+ */
+void CTestDriverService::Release( HANDLE aMutexHandle )
+ {
+ ReleaseMutex( aMutexHandle );
+ }
+
+
+void CTestDriverService::RetrieveConfig()
+ {
+ bool ret = false;
+
+ // Load the configuration information file
+ CUCCIniFile iniFile( KTDServiceIni );
+
+ // Retrieve the port to be used
+ int port;
+ if( iniFile.KeyValue(KIniPort, KIniSectionName, port) )
+ {
+ iPort = port;
+ }
+
+ // Retrieve the exe location/filename
+ string exe;
+ if( iniFile.KeyValue(KIniExeLocation, KIniSectionName, exe) )
+ {
+ iExe = exe;
+ }
+
+ // Retrieve the poll interval
+ int pollInterval;
+ if( iniFile.KeyValue(KIniPollInterval, KIniSectionName, pollInterval) )
+ {
+ iPollInterval = pollInterval;
+ }
+ }
+
+
+int CTestDriverService::AppendCmdLineParams( const CCall& aCall, string &aCmdLine )
+ {
+ int ret = ERR_NONE;
+
+ int numParams = 0;
+ bool callRet = aCall.Params( numParams );
+ if( !ret && callRet && numParams >= 3 )
+ {
+ for( int index=0 ; index<numParams && callRet && !ret ; index++ )
+ {
+ // Retrieve the PLATFORM parameters
+ string name;
+ string value;
+ callRet = aCall.Name( index, name );
+ if( callRet )
+ {
+ callRet = aCall.Value( index, value );
+ }
+
+ if( callRet )
+ {
+ if( name == KPlatform )
+ {
+ aCmdLine += KPlatformFlag;
+ aCmdLine += value;
+ }
+ else if( name == KBuild )
+ {
+ aCmdLine += KBuildFlag;
+ aCmdLine += value;
+ }
+ else if( name == KSuite )
+ {
+ aCmdLine += KSuiteFlag;
+ aCmdLine += value;
+ }
+ else if( name == KTransport )
+ {
+ aCmdLine += KTransportFlag;
+ aCmdLine += value;
+ }
+ else if( name == KLogging )
+ {
+ aCmdLine += KLoggingFlag;
+ aCmdLine += value;
+ }
+ else
+ {
+ ret = ERR_INVALIDARG;
+ }
+ }
+ else
+ {
+ ret = ERR_INVALIDARG;
+ }
+ }
+ }
+ else
+ {
+ ret = ERR_INVALIDARG;
+ }
+
+ return ret;
+ }