|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * CTestDriverService.h |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include <stdlib.h> |
|
22 |
|
23 #include "CAThread.h" |
|
24 #include "CListeningServer.h" |
|
25 #include "CTestDriverService.h" |
|
26 #include "CUCCIniFile.h" |
|
27 |
|
28 // Parameters names |
|
29 const char KPlatform[] = { "PLATFORM" }; |
|
30 const char KBuild[] = { "BUILD" }; |
|
31 const char KSuite[] = { "SUITE" }; |
|
32 const char KTransport[] = { "TRANSPORT" }; |
|
33 const char KLogging[] = { "LOGGING" }; |
|
34 |
|
35 // Ini file names |
|
36 const char KTDServiceIni[] = { ".\\TestDriverService.ini" }; |
|
37 const char KIniSectionName[] = { "TestDriverService" }; |
|
38 const char KIniPort[] = { "Port" }; |
|
39 const char KIniExeLocation[] = { "Exe" }; |
|
40 const char KIniPollInterval[] = { "Poll" }; |
|
41 |
|
42 // TestDriver parameters and flags |
|
43 const char KTDConnection[] = { "localhost" }; |
|
44 const char KDefaultExe[] = { "C:\\apps\\engtools\\testdriver2\\testdriver" }; |
|
45 const char KTDBuild[] = { " build " }; |
|
46 const char KTDRun[] = { " run " }; |
|
47 const char KPlatformFlag[] = { " -p " }; |
|
48 const char KBuildFlag[] = { " -b " }; |
|
49 const char KSuiteFlag[] = { " -s " }; |
|
50 const char KTransportFlag[] = { " -t " }; |
|
51 const char KLoggingFlag[] = { " -l " }; |
|
52 const char KSocketFlag[] = { " -f " }; |
|
53 |
|
54 // TCP Port for TestDriver to use to contact the TestDriverService listening socket |
|
55 const int KDefaultPort = 3002; |
|
56 const int KContinuePollingValue = 1; |
|
57 |
|
58 // Default polling timeout for the Listening Server |
|
59 const int KDefaultPoll = 5; // 5 seconds |
|
60 |
|
61 // Static values to control the thread(s) execution |
|
62 static bool iServerRunning; |
|
63 static bool iTestDriverRunning; |
|
64 static int iTDStartResult; |
|
65 static int iTDCompleteResult; |
|
66 static bool iTDContinuePolling; |
|
67 static bool iTDRunSetupComplete; |
|
68 static char* iRunCommandLine; |
|
69 static CAThread* iServer; |
|
70 static CAThread* iTestDriverRun; |
|
71 static HANDLE iServerMutex; |
|
72 static HANDLE iTDRunMutex; |
|
73 |
|
74 static string iExe; |
|
75 static int iPort; |
|
76 static int iPollInterval; |
|
77 |
|
78 CService* Service() { return new CTestDriverService(); } |
|
79 |
|
80 /* |
|
81 * Constructor |
|
82 */ |
|
83 CTestDriverService::CTestDriverService() |
|
84 { |
|
85 iServerRunning = false; |
|
86 iTestDriverRunning = false; |
|
87 iTDStartResult = 0; |
|
88 iTDCompleteResult = 0; |
|
89 iTDContinuePolling = false; |
|
90 iTDRunSetupComplete = false; |
|
91 iServer = NULL; |
|
92 iRunCommandLine = NULL; |
|
93 iServerMutex = NULL; |
|
94 iTDRunMutex = NULL; |
|
95 iExe = KDefaultExe; |
|
96 iPort = KDefaultPort; |
|
97 iPollInterval = KDefaultPoll; |
|
98 } |
|
99 |
|
100 /* |
|
101 * Destructor |
|
102 */ |
|
103 CTestDriverService::~CTestDriverService() |
|
104 { |
|
105 // Let the Listening Server clean itself up |
|
106 Wait( iServerMutex ); |
|
107 if( iServerRunning ) |
|
108 { |
|
109 iServerRunning = false; |
|
110 } |
|
111 iServer->WaitForThread( -1 ); |
|
112 if( iServer != NULL ) |
|
113 { |
|
114 delete iServer; |
|
115 iServer = NULL; |
|
116 } |
|
117 Release( iServerMutex ); |
|
118 ReleaseMutex( iServerMutex ); |
|
119 CloseHandle( iServerMutex ); |
|
120 |
|
121 // Clean up the TestDriver thread |
|
122 Wait( iTDRunMutex ); |
|
123 if( iTestDriverRunning ) |
|
124 { |
|
125 iTestDriverRunning = false; |
|
126 } |
|
127 iTestDriverRun->WaitForThread( -1 ); |
|
128 if( iTestDriverRun != NULL ) |
|
129 { |
|
130 delete iTestDriverRun; |
|
131 iTestDriverRun = NULL; |
|
132 } |
|
133 |
|
134 // Cleanup the shared command line |
|
135 if( iRunCommandLine != NULL ) |
|
136 { |
|
137 delete [] iRunCommandLine; |
|
138 iRunCommandLine = NULL; |
|
139 } |
|
140 Release( iTDRunMutex ); |
|
141 ReleaseMutex( iTDRunMutex ); |
|
142 CloseHandle( iTDRunMutex ); |
|
143 } |
|
144 |
|
145 |
|
146 /* |
|
147 * Setup |
|
148 * |
|
149 * Creates the mutex's requires by this service |
|
150 */ |
|
151 bool CTestDriverService::Setup() |
|
152 { |
|
153 bool ret = false; |
|
154 |
|
155 // Read the ini file configuration if available, otherwise default |
|
156 RetrieveConfig(); |
|
157 |
|
158 // Create the Listening Server and TestDrive run mutex |
|
159 iServerMutex = CreateMutex( NULL, false, NULL ); |
|
160 iTDRunMutex = CreateMutex( NULL, false, NULL ); |
|
161 |
|
162 if( iServerMutex != NULL && iTDRunMutex != NULL ) |
|
163 { |
|
164 ret = true; |
|
165 } |
|
166 |
|
167 return ret; |
|
168 } |
|
169 |
|
170 /* |
|
171 * RunCommand |
|
172 * |
|
173 * Extracts the call id and delegates to the required functionality |
|
174 */ |
|
175 int CTestDriverService::RunCommand( const CCall& aCall ) |
|
176 { |
|
177 int ret = ERR_INVALID_CALL; |
|
178 bool callRet = false; |
|
179 |
|
180 // Retrieve the call id |
|
181 int callID = -1; |
|
182 callRet = aCall.CallID( callID ); |
|
183 if( callRet ) |
|
184 { |
|
185 switch( callID ) |
|
186 { |
|
187 case 1: // Build and initiate TestDriver (TestExecute) execution |
|
188 { |
|
189 ret = BuildAndRunTestDriver( aCall ); |
|
190 } |
|
191 break; |
|
192 case 2: // Retrieve the TestDriver run execution result |
|
193 { |
|
194 ret = RetrieveTestDriverRunResult(); |
|
195 } |
|
196 break; |
|
197 default: |
|
198 { |
|
199 ret = ERR_INVALID_CALL; |
|
200 } |
|
201 break; |
|
202 } |
|
203 } |
|
204 |
|
205 return ret; |
|
206 } |
|
207 |
|
208 /* |
|
209 * BuildAndRunTestDriver |
|
210 * |
|
211 * Builds all of the dependancies and starts the execution via TestDriver |
|
212 */ |
|
213 int CTestDriverService::BuildAndRunTestDriver( const CCall& aCall ) |
|
214 { |
|
215 int ret = ERR_NONE; |
|
216 |
|
217 // Test to see if the Listening Server is already running |
|
218 // If running, we wait for it exit. |
|
219 Wait( iServerMutex ); |
|
220 if( iServerRunning ) |
|
221 { |
|
222 Release( iServerMutex ); |
|
223 RetrieveTestDriverRunResult(); |
|
224 //ret = ERR_TEST_DRIVER_ALREADY_RUNNING; |
|
225 } |
|
226 else |
|
227 { |
|
228 Release( iServerMutex ); |
|
229 } |
|
230 |
|
231 // Retrieve all the parameters |
|
232 |
|
233 // The build command line |
|
234 string buildCommandLine; |
|
235 buildCommandLine += iExe; |
|
236 buildCommandLine += KTDBuild; |
|
237 if( !ret ) |
|
238 { |
|
239 ret = AppendCmdLineParams( aCall, buildCommandLine ); |
|
240 } |
|
241 |
|
242 // The run command line |
|
243 string runCommandLine; |
|
244 runCommandLine += iExe; |
|
245 runCommandLine += KTDRun; |
|
246 if( !ret ) |
|
247 { |
|
248 ret = AppendCmdLineParams( aCall, runCommandLine ); |
|
249 } |
|
250 |
|
251 // Make the TestDriver build call |
|
252 if( !ret ) |
|
253 { |
|
254 int tdRet = system( buildCommandLine.c_str() ); |
|
255 if( tdRet ) |
|
256 { |
|
257 ret = ERR_TEST_DRIVER_BUILD; |
|
258 } |
|
259 } |
|
260 |
|
261 if( !ret ) |
|
262 { |
|
263 // Append the details for the listening socket |
|
264 runCommandLine += KSocketFlag; |
|
265 runCommandLine += KTDConnection; |
|
266 runCommandLine += ":"; |
|
267 char portBuf[20]; |
|
268 sprintf( portBuf, "%d", iPort ); |
|
269 runCommandLine += portBuf; |
|
270 |
|
271 if( iRunCommandLine != NULL ) |
|
272 { |
|
273 delete [] iRunCommandLine; |
|
274 iRunCommandLine = NULL; |
|
275 } |
|
276 |
|
277 // Setup the command line for the execution thread |
|
278 iRunCommandLine = new char[runCommandLine.length()+1]; |
|
279 strcpy( iRunCommandLine, runCommandLine.c_str() ); |
|
280 } |
|
281 |
|
282 // Start the listening server in its own thread |
|
283 if( !ret ) |
|
284 { |
|
285 // Set the server running flag to true |
|
286 iServerRunning = true; |
|
287 // Kick off the Listening Server in its own thread |
|
288 iServer = new CAThread( "CTestDriverService::ListeningServer" ); |
|
289 int err = 1; |
|
290 TThreadError terr = iServer->StartThread( (void*)CTestDriverService::ListeningServer, NULL, &err ); |
|
291 if( terr != TE_NONE ) |
|
292 { |
|
293 delete iServer; |
|
294 iServer = NULL; |
|
295 ret = ERR_TEST_DRIVER_RUN; |
|
296 } |
|
297 } |
|
298 |
|
299 // Launch TestDriver in run mode in its own thread |
|
300 if( !ret ) |
|
301 { |
|
302 // Set the TestDriver running flag to true |
|
303 iTestDriverRunning = true; |
|
304 // Kick off TestDriver in its own thread |
|
305 iTestDriverRun = new CAThread( "CTestDriverService::TestDriverRun" ); |
|
306 int err = 1; |
|
307 TThreadError terr = iTestDriverRun->StartThread( (void*)CTestDriverService::TestDriverRun, NULL, &err ); |
|
308 if( terr != TE_NONE ) |
|
309 { |
|
310 delete iTestDriverRun; |
|
311 iTestDriverRun = NULL; |
|
312 ret = ERR_TEST_DRIVER_RUN; |
|
313 } |
|
314 } |
|
315 |
|
316 // Retrieve the TestDriver run startup result |
|
317 if( !ret ) |
|
318 { |
|
319 bool cont = false; |
|
320 while( !cont && iTestDriverRunning ) |
|
321 { |
|
322 Sleep( iPollInterval * 1000 ); |
|
323 Wait( iServerMutex ); |
|
324 iTDRunSetupComplete?cont=true:cont=false; |
|
325 Release( iServerMutex ); |
|
326 } |
|
327 Wait( iServerMutex ); |
|
328 iTDStartResult>0?ret=0:ret=ERR_TEST_DRIVER_RUN; |
|
329 iTDRunSetupComplete = false; |
|
330 Release( iServerMutex ); |
|
331 } |
|
332 |
|
333 return ret; |
|
334 } |
|
335 |
|
336 /* |
|
337 * RetrieveTestDriverRunResult |
|
338 * |
|
339 * Retrieves the result upon the TestDriver run completion |
|
340 */ |
|
341 int CTestDriverService::RetrieveTestDriverRunResult() |
|
342 { |
|
343 int ret = ERR_NONE; |
|
344 |
|
345 Wait( iServerMutex ); |
|
346 // Set the continue polling flag |
|
347 iTDContinuePolling = true; |
|
348 Release( iServerMutex ); |
|
349 |
|
350 // The ListeningServer thread will now issue TestDriver with the command |
|
351 // to complete and cleanup and the return code will be set from the TestDriverRun |
|
352 // thread when the executable completes. |
|
353 |
|
354 // Wait for the TestDriverRun thread to complete |
|
355 bool cont = false; |
|
356 while( !cont ) |
|
357 { |
|
358 Sleep( iPollInterval * 1000 ); |
|
359 Wait( iTDRunMutex ); |
|
360 iTestDriverRunning?cont=false:cont=true; |
|
361 Release( iTDRunMutex ); |
|
362 } |
|
363 |
|
364 // Cleanup the threads as they have now completed |
|
365 Wait( iServerMutex ); |
|
366 iServerRunning = false; |
|
367 Release( iServerMutex ); |
|
368 |
|
369 Wait( iTDRunMutex ); |
|
370 iTestDriverRunning = false; |
|
371 Release( iTDRunMutex ); |
|
372 |
|
373 // Now the TestDriver executable has complete return the |
|
374 // appropriate error code |
|
375 if( iTDCompleteResult < 0 ) |
|
376 { |
|
377 ret = ERR_TEST_DRIVER_RUN_COMPLETE; |
|
378 } |
|
379 |
|
380 return ret; |
|
381 } |
|
382 |
|
383 /* |
|
384 * ListeningServer |
|
385 * |
|
386 * Runs the Listening Server |
|
387 * Controlled via the main/TestDriver run thread |
|
388 */ |
|
389 void CTestDriverService::ListeningServer( void ) |
|
390 { |
|
391 // Create a new CListeningServer |
|
392 CListeningServer* server = new CListeningServer(); |
|
393 if( server != NULL ) |
|
394 { |
|
395 // Open it an wait until TestDriver has connected |
|
396 int err = server->Open( iPort ); |
|
397 |
|
398 // Continue if TestDriver connected successfully and the server is set to running |
|
399 // Retrieve the TestDriver execution startup result |
|
400 // Loop until told to stop |
|
401 if( !err ) |
|
402 { |
|
403 int recvInt = 0; |
|
404 iTDStartResult = 0; |
|
405 bool cont = true; |
|
406 while( cont ) |
|
407 { |
|
408 Wait( iServerMutex ); |
|
409 |
|
410 // Attempt to recieve the TestDriver startup code |
|
411 // This recieve call can timeout and we continue retrying |
|
412 err = server->Recieve( recvInt ); |
|
413 if( !err ) |
|
414 { |
|
415 // Set the TestDriver run startup result |
|
416 iTDStartResult = recvInt; |
|
417 iTDRunSetupComplete = true; |
|
418 Release( iServerMutex ); |
|
419 break; |
|
420 } |
|
421 iServerRunning?cont=true:false; |
|
422 Release( iServerMutex ); |
|
423 } |
|
424 } |
|
425 |
|
426 // Check to see that TestDriver has returned a run number. |
|
427 // If it hasn't then the startup has failed. |
|
428 if( iTDStartResult > 0 ) |
|
429 { |
|
430 // Wait until the continue polling flag has been set |
|
431 bool cont = true; |
|
432 while( !err && cont ) |
|
433 { |
|
434 Wait( iServerMutex ); |
|
435 if( iTDContinuePolling ) |
|
436 { |
|
437 err = server->Send( KContinuePollingValue ); |
|
438 // Reset the polling flag |
|
439 iTDContinuePolling = false; |
|
440 Release( iServerMutex ); |
|
441 break; |
|
442 } |
|
443 Release( iServerMutex ); |
|
444 Sleep( iPollInterval * 1000 ); |
|
445 Wait( iServerMutex ); |
|
446 iServerRunning?cont=true:cont=false; |
|
447 Release( iServerMutex ); |
|
448 } |
|
449 } |
|
450 server->Close(); |
|
451 } |
|
452 |
|
453 delete server; |
|
454 server = NULL; |
|
455 Wait( iServerMutex ); |
|
456 iServerRunning = false; |
|
457 Release( iServerMutex ); |
|
458 } |
|
459 |
|
460 /* |
|
461 * TestDriverRun |
|
462 * |
|
463 * Executes the run command for TestDriver |
|
464 */ |
|
465 void CTestDriverService::TestDriverRun( void ) |
|
466 { |
|
467 Wait( iTDRunMutex ); |
|
468 // Launch TestDriver |
|
469 if( iRunCommandLine != NULL ) |
|
470 { |
|
471 iTDCompleteResult = system( iRunCommandLine ); |
|
472 } |
|
473 else |
|
474 { |
|
475 iTDCompleteResult = -1; |
|
476 } |
|
477 |
|
478 // Reset the status to not running |
|
479 iTestDriverRunning = false; |
|
480 Release( iTDRunMutex ); |
|
481 } |
|
482 |
|
483 /* |
|
484 * Wait |
|
485 * |
|
486 * For synchronisation |
|
487 */ |
|
488 void CTestDriverService::Wait( HANDLE aMutexHandle ) |
|
489 { |
|
490 WaitForSingleObject( aMutexHandle, INFINITE ); |
|
491 } |
|
492 |
|
493 /* |
|
494 * Release |
|
495 * |
|
496 * For synchronisation |
|
497 */ |
|
498 void CTestDriverService::Release( HANDLE aMutexHandle ) |
|
499 { |
|
500 ReleaseMutex( aMutexHandle ); |
|
501 } |
|
502 |
|
503 |
|
504 void CTestDriverService::RetrieveConfig() |
|
505 { |
|
506 bool ret = false; |
|
507 |
|
508 // Load the configuration information file |
|
509 CUCCIniFile iniFile( KTDServiceIni ); |
|
510 |
|
511 // Retrieve the port to be used |
|
512 int port; |
|
513 if( iniFile.KeyValue(KIniPort, KIniSectionName, port) ) |
|
514 { |
|
515 iPort = port; |
|
516 } |
|
517 |
|
518 // Retrieve the exe location/filename |
|
519 string exe; |
|
520 if( iniFile.KeyValue(KIniExeLocation, KIniSectionName, exe) ) |
|
521 { |
|
522 iExe = exe; |
|
523 } |
|
524 |
|
525 // Retrieve the poll interval |
|
526 int pollInterval; |
|
527 if( iniFile.KeyValue(KIniPollInterval, KIniSectionName, pollInterval) ) |
|
528 { |
|
529 iPollInterval = pollInterval; |
|
530 } |
|
531 } |
|
532 |
|
533 |
|
534 int CTestDriverService::AppendCmdLineParams( const CCall& aCall, string &aCmdLine ) |
|
535 { |
|
536 int ret = ERR_NONE; |
|
537 |
|
538 int numParams = 0; |
|
539 bool callRet = aCall.Params( numParams ); |
|
540 if( !ret && callRet && numParams >= 3 ) |
|
541 { |
|
542 for( int index=0 ; index<numParams && callRet && !ret ; index++ ) |
|
543 { |
|
544 // Retrieve the PLATFORM parameters |
|
545 string name; |
|
546 string value; |
|
547 callRet = aCall.Name( index, name ); |
|
548 if( callRet ) |
|
549 { |
|
550 callRet = aCall.Value( index, value ); |
|
551 } |
|
552 |
|
553 if( callRet ) |
|
554 { |
|
555 if( name == KPlatform ) |
|
556 { |
|
557 aCmdLine += KPlatformFlag; |
|
558 aCmdLine += value; |
|
559 } |
|
560 else if( name == KBuild ) |
|
561 { |
|
562 aCmdLine += KBuildFlag; |
|
563 aCmdLine += value; |
|
564 } |
|
565 else if( name == KSuite ) |
|
566 { |
|
567 aCmdLine += KSuiteFlag; |
|
568 aCmdLine += value; |
|
569 } |
|
570 else if( name == KTransport ) |
|
571 { |
|
572 aCmdLine += KTransportFlag; |
|
573 aCmdLine += value; |
|
574 } |
|
575 else if( name == KLogging ) |
|
576 { |
|
577 aCmdLine += KLoggingFlag; |
|
578 aCmdLine += value; |
|
579 } |
|
580 else |
|
581 { |
|
582 ret = ERR_INVALIDARG; |
|
583 } |
|
584 } |
|
585 else |
|
586 { |
|
587 ret = ERR_INVALIDARG; |
|
588 } |
|
589 } |
|
590 } |
|
591 else |
|
592 { |
|
593 ret = ERR_INVALIDARG; |
|
594 } |
|
595 |
|
596 return ret; |
|
597 } |