os/security/cryptomgmtlibs/securitytestfw/test/autotesting/test_launcher.pl
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 #
     2 # Copyright (c) 2008-2010 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 the License "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 # This script runs security tests for chosen components on a local machine without DABS scripts and ONB. Follow the steps below
    16 # in order to launch tests for a security component:
    17 # 1. Choose a local drive to be used, e.g. p:
    18 # 2. Download a CBR onto the chosen drive.
    19 # 3. Download the security source tree onto the chosen drive, and ensure that your environment variable 
    20 # SECURITYSOURCEDIR points to the relevant root directory.  It helps to use a drive independant value here 
    21 # as this will allow concurrent builds and test runs on seperate drives (assuming the source code has the same path in each case).
    22 # 4. Download ExecTimeOut.exe, which is stored at //PR/share/DABSRelease/buildscripts/, onto the relevant location
    23 # (by default this is the chosen drive's root).  
    24 # 5. Build the security code.  Note that builds require the SECURITYSOURCEDIR environment variable to be set.
    25 # 6. Run or modify the relevant wrapper batch file for your component, which will be stored in the root of the test directory.
    26 # Components Summary
    27 # This script works fine with the following components: Asnpkcs, Caf2, Certman, Common, Crypto, Cryptospi, CryptoTokens,
    28 # FileTokens, Sistools, Streamingcaf, Swi, Switools, Ups. Other components must be tested and therefore 
    29 # further extensions may be needed.
    30 #
    31 
    32 use Cwd;
    33 use Getopt::Long;
    34 
    35 ########################### Start of Input Reading Block ###########################
    36 
    37 # Check environment variable SECURITYSOURCEDIR is correctly set
    38 if ($ENV{'SECURITYSOURCEDIR'} eq "")
    39 	{
    40 	die "ERROR: The SECURITYSOURCEDIR environment variable has not been set.  Set this to point to the root of the security source tree on your drive and rebuild the components you want to test.  If you want to perform concurrent builds/tests use a drive relative value and use the same directory structure on each drive.";
    41 	}
    42 else
    43 	{
    44 	my $current_dir = getcwd();
    45 	$current_dir =~ /^(\D):/;	# $1 = driveletter
    46 	
    47 	my $current_drive = lc $1;	
    48 
    49 	$ENV{'SECURITYSOURCEDIR'} =~ /^(\D):/;	# $1 = driveletter if it exists
    50 	my $sourcedir_drive =  lc $1;
    51 
    52 	if (($sourcedir_drive ne "") && ($sourcedir_drive ne $current_drive))
    53 		{
    54 		print "WARNING: Your SECURITYSOURCEDIR environment variable is set to an absolute path and points to a different drive than the current one\n" . "SECURITYSOURCEDIR=  " . $ENV{'SECURITYSOURCEDIR'} . "\nAre you sure you want to continue (Y/N)?\n";
    55 		my $user_decision = <STDIN>;
    56 		$user_decision = lc $user_decision;
    57 		$user_decision =~ /^(.*)\n/;
    58 		if (($1 ne "y") && ($1 ne "yes"))
    59 			{
    60 			die "User decided not to continue, quiting...";
    61 			}
    62 		}
    63 	}
    64 
    65 # Read in command line arguments
    66 my $testedComponentsRaw;
    67 my @testedComponents;
    68 my $testedReleasesRaw;
    69 my @testedReleases;
    70 my $ExecTimeOut;
    71 my $resultsOutputDir;
    72 my $skipCleanAfterFinalComponent;
    73 my $suppressBrowserPopup;
    74 my $displayHelp;
    75 
    76 GetOptions("components=s" => \$testedComponentsRaw, 
    77 	   "testReleases=s" => \$testedReleasesRaw,
    78 	   "resultsoutput=s" => \$resultsOutputDir,
    79 	   "exectimeout=s" => \$ExecTimeOut,
    80 	   "suppressbrowser" => \$suppressBrowserPopup,
    81 	   "skipfinalclean" => \$skipCleanAfterFinalComponent,
    82 	   "help" => \$displayHelp);
    83 
    84 if ($displayHelp)
    85 {
    86 	DisplayHelp();
    87 }
    88 
    89 # Ensure necessary arguments are present
    90 $shouldIDie = 0;
    91 
    92 while ($testedComponentsRaw =~ s/([^,]*),//)
    93 {
    94 	push(@testedComponents, $1);
    95 }			
    96 if ($testedComponentsRaw =~ /\S/)
    97 {	
    98 	push(@testedComponents, $testedComponentsRaw);
    99 }
   100 else
   101 {
   102 	print "ERROR: Components to be tested not listed (e.g. -components caf2,streamingcaf).\n";
   103 	$shouldIDie = 1;
   104 }
   105 
   106 while ($testedReleasesRaw =~ s/([^,]*),//)
   107 {
   108 	push(@testedReleases, $1);
   109 }
   110 if ($testedReleasesRaw =~ /\S/)
   111 {
   112 	push(@testedReleases, $testedReleasesRaw);
   113 }
   114 else
   115 {			
   116 	print "ERROR: Releases to be tested not listed (e.g. -testReleases udeb,urel).\n";
   117 	$shouldIDie = 1;		
   118 }
   119 
   120 
   121 if (!defined $ExecTimeOut)
   122 {
   123 	print "ERROR: Location of ExecTimeOut.exe not specified (e.g. -exectimeout \\ExecTimeOut.exe).\n";
   124 	$shouldIDie = 1;
   125 }
   126 if (!defined $resultsOutputDir)
   127 {
   128 	print "ERROR: Directory to place test results not specified (e.g. -resultsoutput \\logs\\winscw).\n";
   129 	$shouldIDie = 1;
   130 }
   131 
   132 if ($shouldIDie)
   133 {
   134 	die "Input parameters incorrect, exiting.";
   135 }
   136 
   137 
   138 
   139 my $buildTarget = 'winscw';	# At the moment the script only works for winscw
   140 my $testSpec = "$ENV{SECURITYSOURCEDIR}\\testframework\\test\\autotesting\\test_spec.txt";
   141 my $testResultsPath = "$resultsOutputDir\\TestResults_Summary.html";
   142 ############################ End of Input Reading Block ############################
   143  
   144 
   145 use Text::ParseWords;
   146 use File::Path 'rmtree';
   147 
   148 # helper functions
   149 sub ExecCmd;
   150 
   151 #  helper functions taken from the TestUtilities.pm perl module
   152 sub FullWin32Path;
   153 sub FullPathToCDrive;
   154 sub FullPathToZDrive;
   155 sub DigestSecurityTestLog;
   156 sub DigestTestExecuteTestLog;
   157 
   158 # create/empty directory for epoc window output files
   159 ExecCmd("rmdir /s /q $resultsOutputDir");
   160 ExecCmd("mkdir $resultsOutputDir");
   161 
   162 # set the location of epoc window output
   163 my $tempDir=$ENV{'TMP'};
   164 my $epocWndPath = $tempDir.'\epocwind.out';
   165 
   166 ExecCmd('mkdir \epoc32\drive_d');
   167 ExecCmd('mkdir \epoc32\drive_e');
   168 ExecCmd('mkdir \epoc32\drive_r');
   169 
   170 if (!grep(/PlatSecDisabledCaps SwEvent/, ReadFile('\epoc32\data\epoc.ini')))
   171 	{
   172 	# set up drives for emulator	
   173 	ExecCmd('echo _epoc_drive_d \epoc32\drive_d >> \epoc32\data\epoc.ini');
   174 	ExecCmd('echo _epoc_drive_e \epoc32\drive_e >> \epoc32\data\epoc.ini');
   175 	ExecCmd('echo _epoc_drive_r \epoc32\drive_r >> \epoc32\data\epoc.ini');
   176 
   177 	# disable the SwEvent to test SWI's handling of loader grantable capabilities
   178 	ExecCmd('echo PlatSecDisabledCaps SwEvent >> \epoc32\data\epoc.ini');
   179 
   180 	# turn off panic dialogs requiring user interaction
   181 	ExecCmd('echo JustInTime none >> \epoc32\data\epoc.ini');
   182 	}
   183 
   184 # remove watchers
   185 ExecCmd('del /Q /F /S \epoc32\release\wins\*watcher.dll');
   186 ExecCmd('del /Q /F /S \epoc32\release\winscw\*watcher.dll');
   187 
   188 # replace custom Java Installer with test version
   189 my $cmiPath = "\\epoc32\\release\\$buildTarget\\$testedRelease";
   190 if ( -f "$cmiPath\\custommidletinstall.dll" && -f "$cmiPath\\tcustommidletinstall.dll" )
   191 {
   192     ExecCmd("ren $path\\custommidletinstall.dll custommidletinstall.std");
   193     ExecCmd("copy $path\\tcustommidletinstall.dll $path\\custommidletinstall.dll");
   194 }
   195 
   196 rmtree("$ENV{'EPOCROOT'}backup\\wins\\c");
   197 rmtree("$ENV{'EPOCROOT'}backup\\winscw\\c");
   198 rmtree("$ENV{'EPOCROOT'}backup\\drive_d");
   199 rmtree("$ENV{'EPOCROOT'}backup\\drive_e");
   200 
   201 # create backups of the current drive states
   202 ExecCmd("xcopy /y/e/i/q $ENV{'EPOCROOT'}epoc32\\wins\\c $ENV{'EPOCROOT'}backup\\wins\\c");	
   203 ExecCmd("xcopy /y/e/i/q $ENV{'EPOCROOT'}epoc32\\winscw\\c $ENV{'EPOCROOT'}backup\\winscw\\c");	
   204 ExecCmd("xcopy /y/e/i/q $ENV{'EPOCROOT'}epoc32\\drive_d $ENV{'EPOCROOT'}backup\\drive_d");
   205 ExecCmd("xcopy /y/e/i/q $ENV{'EPOCROOT'}epoc32\\drive_e $ENV{'EPOCROOT'}backup\\drive_e");
   206 
   207 # clean the results folder
   208 rmtree("$resultsOutputDir");
   209 ExecCmd("mkdir $resultsOutputDir");
   210 
   211 # open test result file
   212 if (!open(TESTRESULTS, ">$testResultsPath"))
   213 {
   214     die "Can't open output file $testResultsPath";
   215 }
   216 
   217 # create HTML header
   218 print TESTRESULTS "<html>\n<head>\n<title>Title of page</title>\n</head>";
   219 print TESTRESULTS "\n<body>\n<h2 align=\"center\">Test Results</h2>\n";
   220 print TESTRESULTS "<p><b>target:</b> $buildTarget<br>\n";
   221 print TESTRESULTS "<b>security sources:</b> $ENV{SECURITYSOURCEDIR}<br>\n";
   222 print TESTRESULTS "<b>test spec:</b> $testSpec<br>\n";
   223 print TESTRESULTS "<b>tested components:</b> @testedComponents</p>\n";
   224 print TESTRESULTS "<table border=\"1\">\n<tr bgcolor=\"gray\"><th>#</th><th>Component</th><th>Release</th><th>Program</th><th>Script</th><th>Results</th><th>Log file</th><th>Epoc window</th></tr>";
   225 
   226 # for the first component being tested there is no need to perform a restore on the drives, this variable is used to make this optimisation
   227 my $firstTestedComponent = 1;
   228 
   229 my $i = 0;
   230 
   231 foreach my $testedRelease (@testedReleases)
   232 {
   233 	$logSuffix = '';
   234 	if ($testedRelease eq 'urel')
   235 	{
   236 		$logSuffix = '1';	# so that the udeb results aren't overwritten by urel ones, matches ONB labelling
   237 	}
   238 
   239 	# open test spec file
   240 	if (!open(TESTSPEC, "<$testSpec"))
   241 	{
   242     	die "Can't open input file $testSpec";
   243 	}
   244 
   245 	# set current directory
   246 	chdir("$ENV{'EPOCROOT'}epoc32\\release\\$buildTarget\\$testedRelease");
   247 
   248 	# walk through the test spec file line-by-line and execute matching tests
   249 	my $curComponent = '';
   250 
   251 	my $testingCurrentComponent = 0;
   252 
   253 	while (<TESTSPEC>)
   254 	{
   255     	# skip comment lines
   256     	my $line = $_;
   257     	if ($line =~ /^\s*#/)
   258     	{  
   259         	next;
   260     	}
   261     
   262     	# set current component
   263     	if ($line =~ /^\s*\[\s*(\w+)\s*\]/) #find [component name] line
   264 		{
   265 			$curComponent = $1;
   266 			print "\n[$curComponent]\n";
   267 		
   268 			# determine if we are testing this component.
   269 			if (!grep(/^$curComponent$/i,@testedComponents)) 
   270 			{
   271 				$testingCurrentComponent = 0;
   272 				next;
   273 			}
   274 		
   275 			$testingCurrentComponent = 1;		
   276 			# clean the system and mmc drives if necessary
   277 			if ($firstTestedComponent)
   278 			{
   279 				$firstTestedComponent = 0;
   280 			}
   281 			else
   282 			{
   283 				ExecCmd("$ENV{SECURITYSOURCEDIR}\\testframework\\test\\autotesting\\restoredrivesstates.bat");	# For some reason when these commands are executed directly from Perl the call to xcopy to backup winscw\c causes xcopy to halt after copying one of the kanji SIS files, as a call to a batch file the commands work correctly.
   284 			}
   285 			# setup ethernet support on the emulator
   286 			ExecCmd("$ENV{SECURITYSOURCEDIR}\\testframework\\test\\autotesting\\useautocfg.bat");
   287 			next;
   288 		}
   289     
   290     	# execute the test if we are testing this component
   291     	if ($testingCurrentComponent) 
   292     	{
   293     		my $program = '';
   294         	my $log = '';
   295         	my $commdb = '';
   296         	my $script = '';
   297         	my $timeout = '';
   298         	my $release = '';
   299         	my $preCommand = '';
   300         	my $postCommand = '';
   301         
   302                 
   303         	# parse line from the test spec file
   304         	($program, $log, $commdb, $script, $timeout, $release, $preCommand, $postCommand) = quotewords(',', 1, $line);
   305         
   306 
   307         
   308         	$program =~ s/^\s*//;
   309         	$program =~ s/\s*$//;
   310         	$script =~ s/^\s*//;
   311         	$script =~ s/\s*$//;
   312         	$preCommand =~ s/^\s*//;
   313         	$preCommand =~ s/\s*$//;
   314         	$preCommand =~ s/%SECURITYSOURCEDIR%/$ENV{SECURITYSOURCEDIR}/;
   315         	$postCommand =~ s/^\s*//;
   316         	$postCommand =~ s/\s*$//;
   317         	$postCommand =~ s/%SECURITYSOURCEDIR%/$ENV{SECURITYSOURCEDIR}/;
   318         	$log =~ s/^\s*//;
   319         	$log =~ s/\s*$//;
   320 
   321         
   322        		# check release
   323         	if($release =! /$testedRelease/i)
   324         	{
   325             	next;
   326         	}
   327         	$i++;
   328      
   329         	# execute the pre-test command
   330         	if($preCommand ne "")
   331         	{
   332             	ExecCmd($preCommand);
   333         	}
   334         
   335         	# execute the test command
   336         	ExecCmd("$ExecTimeOut \"$program $script\" $timeout");
   337         	print "\n\nExecution of $program $script";
   338 
   339        
   340         	# store test results and epoc window output files    
   341         	my $bEpocWnd = 0;
   342     
   343     		$trimmedLog = $log;
   344     		$trimmedLog =~ s/\\.*\\//;	# perl does greedy pattern matching so strips off all directories in the path of the form \....\....\
   345 			$trimmedLog =~ s/.*\\//;	# in case the path is relative strip of the leading directory
   346 			$trimmedLog =~ /(.*)\.([^\.]*)/;	# extract the filename and the extension
   347 
   348       		$epocwindName = $1 . $logSuffix . "_epocwind.txt";
   349       		$targetLogName = $1 . $logSuffix. "\." . $2;
   350       	
   351         	ExecCmd("copy $epocWndPath $resultsOutputDir\\$epocwindName");
   352         	ExecCmd("del $epocWndPath");
   353         	$bEpocWnd = 1;
   354      
   355         
   356         	# process log files
   357         	my $sText = "";
   358         	my $iPass = 0;
   359         	my $iFail = 0;
   360         	my $iPass_case = 0;	# not used
   361         	my $iFail_case = 0;	# not used
   362         	my $bLogFile = 0;
   363         	my $logPath = FullWin32Path($buildTarget, $release, $log);
   364         	if (-f $logPath)
   365         	{
   366             	$bLogFile = 1;
   367             	ExecCmd("copy $logPath $resultsOutputDir\\$targetLogName");
   368     			# Test Execute
   369     			if ($sText eq "")
   370     			{
   371     				($sText, $iPass, $iFail, $iPass_case, $iFail_case) = DigestTestExecuteTestLog($logPath);
   372     			}
   373     	
   374     			# Security Test Logs
   375     			if ($sText eq "" )
   376     			{
   377     				# Check to see if this is an Security RTest test log
   378     				($sText, $iPass, $iFail) = DigestSecurityTestLog($logPath);
   379     			}
   380         
   381             	# get rid of surrounding html tags
   382             	if ($sText)
   383             	{
   384                 	if ($sText =~ /<td.*>(.+)<\/td>/)
   385                 	{
   386                     	$sText = $1;
   387                 	}
   388             	}
   389         	}
   390         
   391         	# generate HTML results
   392         	my $htmlEpocWnd = "<a href=\"$resultsOutputDir\\$epocwindName\">here</a>";
   393         	if(!$bEpocWnd)
   394         	{
   395             	$htmlEpocWnd = "not found";
   396         	}
   397         	my $htmlColor = "white";
   398         	my $htmlLog = "<a href=\"$resultsOutputDir\\$targetLogName\">$log</a>";
   399         
   400         	if($bLogFile)
   401         	{
   402             	if ($sText eq "" )
   403             	{
   404                 	$htmlColor = 'blue';
   405                 	$sText = 'log file not parsed';
   406             	}
   407             	elsif(!$iPass or $iFail)
   408             	{
   409                 	$htmlColor = "red";
   410             	}
   411         	}
   412         	else
   413         	{
   414             	$htmlColor = 'yellow';
   415             	$sText = 'log file not found';
   416             	$htmlLog = '';
   417         	}
   418            
   419         	print TESTRESULTS "\n<tr bgcolor=\"$htmlColor\">";
   420         	print TESTRESULTS "<td>$i</td><td>$curComponent</td><td>$testedRelease</td><td>$program</td><td>$script</td>";
   421         	print TESTRESULTS "<td>$sText</td><td>$htmlLog</td><td>$htmlEpocWnd</td></tr>";
   422 
   423         	print "\nResults: $sText";
   424         
   425         	# execute the post-test command
   426         	if($postCommand ne "")
   427         	{
   428         	    ExecCmd($postCommand);
   429         	}
   430     	}
   431 	}
   432 	close TESTSPEC;
   433 }
   434 
   435 # restore the drives' states
   436 if (!$skipCleanAfterFinalComponent)
   437 {
   438 	ExecCmd("$ENV{SECURITYSOURCEDIR}\\testframework\\test\\autotesting\\restoredrivesstates.bat");
   439 }	
   440 
   441 # final html stuff
   442 print TESTRESULTS "\n</table></body></html>";
   443 
   444 close TESTRESULTS;
   445 
   446 if (!$suppressBrowserPopup)
   447 {
   448 	# open test results in browser, this will halt script execution until the browser is closed
   449 	`$testResultsPath`;
   450 }	
   451 
   452 ######################################################################################
   453 #  helper functions
   454 ######################################################################################
   455 sub ExecCmd
   456 {
   457 	my $cmd = $_[0];
   458     print "\n".`$cmd`;
   459 }
   460 
   461 sub DisplayHelp {
   462 	print "\n\n\nHELP DIALOG:";
   463 	print "\nThe following arguments are required:\n\n";
   464 	print "-components: A comma separated (no spaces) list of component names.\n\n";
   465 	print "-testreleases: A comma separated (no spaces) list of the releases tested.\n\n";
   466 	print "-exectimeout: The path location of ExecTimeOut.exe relative to this drive.  This is downloaded via Perforce from //PR/share/DABSRelease/buildscripts/ExecTimeOut.exe.\n\n";
   467 	print "-resultsoutput: Directory used to store the test results and epocwind.out files from running the tests.  Current contents will be deleted.  Use a value of \\logs\\winscw if you want it to be compatible with the panicscan test.\n\n";
   468 	print "-skipfinalclean: The script will restore the drives to their original state after each component has been tested.  If you do not want the drives to be restored after the final component has been tested (typically used when debugging just one component's tests) then add this flag and before re-running the tests manually restore the drives from the contents of the \\backup\\ folder.\n\n";
   469 	print "-suppressbrowser: Add this flag to prevent the halting of execution and presentation of the results in a browser window after the tests have been run.";
   470 	print "Example usage:\n";
   471 	print "test_launcher.pl -components caf2,streamingcaf,swi -testreleases udeb,urel -exectimeout \\ExecTimeOut.exe resultsoutput \\logs\\winscw -skipfinalclean -suppressbrowser\n\n";
   472 	die;
   473 }
   474 
   475 ######################################################################################
   476 # helper functions taken from the TestUtilities.pm perl module
   477 ######################################################################################
   478 
   479 sub DigestTestExecuteTestLog
   480 # Arg: [0] output log from a TestExecute run
   481 # Returns: small HTML summary string of the run
   482 {
   483 	my $filename = $_[0];
   484 	my $TestConfirmed = $_[1];
   485 	my $sHTML = "";
   486  
   487 	$filename =~ s/\s+$//;
   488 	return "" unless( -f $filename and open( TEST, $filename )); 
   489 
   490 	$/ = "\n";
   491 
   492 	my $iFail = 0;
   493 	my $iPass = 0;
   494 	my $iCheck = 0;
   495 	my $bTestExecute = 0;
   496 	my $TEST_STEP_SECTION = 0;
   497 	my $iFail_case = 0;
   498 	my $iPass_case = 0;
   499 	my $iCheck_case = 0;
   500 	my $TEST_CASE_SECTION = 0;
   501 	
   502 
   503 	while( <TEST> )
   504 	{
   505 		chomp;
   506 		my $sLine = $_;
   507 		if ( $sLine =~ /TEST STEP SUMMARY:<\/font>/i) 
   508 		{
   509 			$TEST_STEP_SECTION = 1;
   510 			$TEST_CASE_SECTION = 0;
   511 		}
   512 		elsif ( $sLine =~ /RUN PROGRAM SUMMARY:<\/font>/i) 
   513 		{
   514 			$TEST_STEP_SECTION = 0;
   515 		}
   516 	        elsif( $sLine =~ /TEST CASE SUMMARY:<\/font>/i)
   517 		{
   518 			$TEST_CASE_SECTION = 1;
   519 			$TEST_STEP_SECTION = 0;
   520 		}		
   521 		elsif ( $sLine =~ /SUMMARY:<\/font>/i ) # To Keep Last
   522 		{
   523 			$TEST_STEP_SECTION = 1;
   524 		}
   525 		if ( $TEST_STEP_SECTION )
   526 		{
   527 			$iPass += $1 if( $sLine =~ /<font.*color=00AF00> PASS = (\d+)<\/font>/i);
   528 			$iPass += $1 if( $sLine =~ /<font.*color=00AF00>PASS = (\d+)<\/font>/i);
   529 		
   530 			$iFail += $1 if( $sLine =~ /<font.*color=FF0000>FAIL = (\d+)<\/font>/i);
   531 			$iFail += $1 if( $sLine =~ /<font.*color=0000FF>ABORT = (\d+)<\/font>/i);
   532 			$iFail += $1 if( $sLine =~ /<font.*color=0000FF>PANIC = (\d+)<\/font>/i);
   533 			$iFail += $1 if( $sLine =~ /<font.*color=0000FF>INCONCLUSIVE = (\d+)<\/font>/i);
   534 			$iFail += $1 if( $sLine =~ /<font.*color=0000FF>UNKNOWN = (\d+)<\/font>/i);
   535 			$iFail += $1 if( $sLine =~ /<font.*color=0000FF>UNEXECUTED = (\d+)<\/font>/i);
   536 		}
   537 		if ( $TEST_CASE_SECTION )
   538 		{
   539 
   540 			$iPass_case += $1 if( $sLine =~ /<font.*color=00AF00> PASS = (\d+)<\/font>/i);
   541 			$iPass_case += $1 if( $sLine =~ /<font.*color=00AF00>PASS = (\d+)<\/font>/i);
   542 			$iFail_case += $1 if( $sLine =~ /<font.*color=FF0000>FAIL = (\d+)<\/font>/i);
   543 			$iFail_case += $1 if( $sLine =~ /<font.*color=0000FF>ABORT = (\d+)<\/font>/i);
   544 			$iFail_case += $1 if( $sLine =~ /<font.*color=0000FF>PANIC = (\d+)<\/font>/i);
   545 			$iFail_case += $1 if( $sLine =~ /<font.*color=0000FF>INCONCLUSIVE = (\d+)<\/font>/i);
   546 			$iFail_case += $1 if( $sLine =~ /<font.*color=0000FF>UNKNOWN = (\d+)<\/font>/i);
   547 			$iFail_case += $1 if( $sLine =~ /<font.*color=0000FF>UNEXECUTED = (\d+)<\/font>/i);
   548 			
   549 		}
   550 		$bTestExecute = 1 if( $sLine =~ /\*\*\*\s+TestExecute\s+Started/i);
   551 
   552 	}
   553 	close( TEST );
   554 	
   555 	if( $bTestExecute )
   556 	{
   557 		if(( $iPass == 0 and $iFail == 0) and ($TestConfirmed == 1))
   558 		{
   559 			$sHTML = "<td>$iPass passed, $iFail failed</td>";
   560 		}
   561 		elsif ( $iPass == 0 and $iFail == 0)
   562 		{
   563 			$sHTML = "<td $sFailedBGColor>test crashed</td>";
   564 		}
   565 		elsif( $iFail > 0 )
   566 		{
   567 			$sHTML = "<td $sFailedBGColor>$iPass passed, $iFail failed</td>";
   568 		}
   569 		else
   570 		{
   571 			$sHTML = "<td>$iPass passed, $iFail failed</td>";
   572 		}
   573 	}
   574 	elsif( $iPass > 0 or $iFail > 0 )
   575 	{
   576 		#
   577 		# Almost certainly a TEF log, but missing the "TestExecute Started" line.
   578 		# Possibly because of a loss of part of the log from the hardware.
   579 		#
   580 		if( $iFail > 0 )
   581 		{
   582 			$sHTML = "<td $sFailedBGColor>$iPass passed, $iFail failed</td>";
   583 		}
   584 		else
   585 		{
   586 			$sHTML = "<td  $sWarningBCColor>$iPass passed, $iFail failed</td>";
   587 		}
   588 	}
   589 	 	 
   590 	return ($sHTML, $iPass, $iFail, $iPass_case, $iFail_case);
   591 }
   592 
   593 
   594 sub DigestSecurityTestLog
   595 # Arg: [0] output log from an automated testcase run
   596 # Returns: small HTML summary string of the run indicating test result extracted from log.
   597 {	
   598 	my $filename = $_[0];
   599 
   600 	my $sHTML = "";
   601  
   602 	my $sCmd = "type $filename |";
   603 	$filename =~ s/\s+$//;
   604 	return "" unless( -f $filename and open( TEST, $sCmd )); 
   605 
   606 	$/ = "\n";
   607 
   608 	# For these tests the result x tests failed out of y is displayed in the 2nd last line of the log file. 
   609     
   610 	my $iFail = 0;
   611 	my $iPass = 0;
   612 	my $iTotal = 0;
   613 
   614 	while( <TEST> )
   615 	{
   616 		chomp;
   617 		my $sLine = $_;
   618 		my $null = chr(0);
   619 		$sLine =~ s/$null|\s//g;
   620 		if( $sLine =~ /(\d+)testsfailedoutof(\d+)/i )
   621 		{
   622 			$iFail += $1;
   623 			$iTotal += $2;
   624 		}
   625 	}
   626 	close( TEST );
   627 	
   628 	if( $iTotal > 0 )
   629 	{
   630 		$sHTML = "<td>";
   631 		$sHTML = "<td $sFailedBGColor>" if( $iFail > 0 );
   632 
   633 		$iPass = $iTotal - $iFail;
   634 		$sHTML .= "$iPass passed, $iFail failed</td>";
   635 	}
   636 	 	 
   637 	return ($sHTML, $iPass, $iFail);
   638 }
   639 
   640 ######################################################################################
   641 # helper functions taken from the BuildSpecifications.pm perl module
   642 ######################################################################################
   643 
   644 # Read the contents of a file into a string and return it
   645 sub ReadFile ($)
   646 {
   647 	my ($file) = @_;
   648 	open FILE, "<$file" or LogDie("Can't read file: $file", @StdLogs);
   649 	local $/ = undef;
   650 	my $data = <FILE>;
   651 	close FILE;
   652 	return $data;
   653 }
   654 
   655 
   656 ###########################################################################
   657 # Return Path to z Drive
   658 # Arguments: [0] Build Target (e.g. arm4, wins, etc)
   659 #            [1] Build Release (Optional) (e.g. UDEB/UREL)
   660 # Returns Correspoonding Effective Z Drive
   661 sub FullPathToZDrive
   662 {
   663 	my ($buildTarget, $buildRelease) = @_;
   664 	$buildRelease="UDEB" unless( $buildRelease );
   665 
   666 	return "$ENV{'EPOCROOT'}epoc32\\release\\$buildTarget\\$buildRelease\\z" if( $buildTarget =~ /wins/i );
   667 	return "$ENV{'EPOCROOT'}epoc32\\data\\z";
   668 }
   669 
   670 
   671 ###########################################################################
   672 # Return Path to C Drive
   673 # Arguments: [0] Build Target (e.g. arm4, wins, etc)
   674 # Returns Correspoonding Effective C Drive
   675 sub FullPathToCDrive
   676 {
   677 	my ($buildTarget) = @_;
   678 
   679 	return "$ENV{'EPOCROOT'}epoc32\\$buildTarget\\c" if( $buildTarget =~ /wins/i );
   680 	return "$ENV{'EPOCROOT'}epoc32\\data\\z";
   681 }
   682 
   683 
   684 ###########################################################################
   685 # EPOC paths can be drive-relative ("\scripts\bob") or absolute ("c:\scripts\bob"). 
   686 # Return an appropriate Win32 path, where - an additional complication
   687 # is that the EPOC c: and z: aren't sibling Win32 paths
   688 # Arguments: [0] Build Target (e.g. arm4, wins, etc)
   689 #            [1] Build Release (Optional) (e.g. UDEB/UREL)
   690 #            [2] EPOC path
   691 # Returns: full Win32 path
   692 sub FullWin32Path
   693 {
   694 	my ($buildTarget, $buildRelease, $sPath) = @_;
   695 
   696 	$sPath =~ s/^\s+//;
   697 	if($sPath =~ /^(\w):(.*)/)
   698 	{
   699 		my $sDrive = uc($1);
   700 		my $sDir = $2;
   701 		$sDir =~ s/^\\//;
   702 		if($sDrive eq "C")
   703 		{
   704 			return FullPathToCDrive($buildTarget) . "\\$sDir";
   705 		}
   706 		elsif($sDrive eq "Z")
   707 		{
   708 			return FullPathToZDrive($buildTarget,$buildRelease) . "\\$sDir";
   709 		}
   710 		else
   711 		{
   712 			# Maybe an actual pathname
   713 			return $sPath;
   714 		}
   715 	}
   716 	
   717 	# Presumption is that path is relative to EPOC C:\
   718 	$sPath =~ s/^\\//;
   719 	return FullPathToCDrive($buildTarget) . "\\$sPath";
   720 }