mmtestenv/mmtesttools/Scripts/TestResultsComparisonTool/ResultsComparison.pl
changeset 24 2672ba96448e
equal deleted inserted replaced
21:1c0a769d0cc5 24:2672ba96448e
       
     1 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # All rights reserved.
       
     3 # This component and the accompanying materials are made available
       
     4 # under the terms of "Eclipse Public License v1.0"
       
     5 # which accompanies this distribution, and is available
       
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 #
       
     8 # Initial Contributors:
       
     9 # Nokia Corporation - initial contribution.
       
    10 #
       
    11 # Contributors:
       
    12 #
       
    13 # Description:
       
    14 #
       
    15 
       
    16 use strict;
       
    17 use LWP::Simple;
       
    18 use TestScriptResults;
       
    19 use Getopt::Std;
       
    20 use File::Find;
       
    21 
       
    22 # Mistral tags the result files from test scripts in a particular format, depending on the test harness used to execute them. 
       
    23 # We use these names to identify which files are results files.
       
    24 my $KMistralCoreConfFileName = "-coreconf-";
       
    25 my $KMistralTEFFileName = "-testexecute-";
       
    26 my $KMistralTestFrameworkFileName = "-testframework"; # No trailing hyphen due to different security variants
       
    27 
       
    28 #  It appears that Mistral uses a completely different file format for results from HW runs
       
    29 my $KMistrealTEFFileNameHW = "testexecute";
       
    30 my $KMistrealTFFileNameHW1 = "testframework";
       
    31 my $KMistrealTFFileNameHW2 = "testframeworkmmddcap";
       
    32 my $KMistrealTFFileNameHW3 = "testframeworkuecap";
       
    33 my $KMistrealTFFileNameHW4 = "testframeworknone";
       
    34 
       
    35 # Work in progress script outputs.
       
    36 my $iKnownFails;
       
    37 my $iUnknownFailsButKnownInRef;
       
    38 my $iUnknownFailsButKnownInOtherCodelines;
       
    39 my $iUnknownFails;
       
    40 my $iMissingTests; 	
       
    41 
       
    42 my $iVerbose;
       
    43 
       
    44 ###############################################
       
    45 ##	Source test domain specific functionality
       
    46 ###############################################
       
    47 # Scans the test results summary page from the Mistral build and compiles a collection of the 
       
    48 # URL paths for the log files.
       
    49 # param1 - the URL to the Test Results HTML Summary page of the Mistral build
       
    50 # returns - the array of logs' URLS
       
    51 sub GetResultFilesFromMistral
       
    52 	{
       
    53 	my $aMistralTestResultsSummaryUrl = shift;
       
    54 
       
    55 	my @fileNames;
       
    56 	my $nextFileNamesIndex = 0;
       
    57 
       
    58 	my $summaryContents = get "$aMistralTestResultsSummaryUrl"; # Returns undef if failure
       
    59 	unless ($summaryContents)
       
    60 		{
       
    61 		print "\nERROR: Unable to retrieve source summary file from $aMistralTestResultsSummaryUrl\n";
       
    62 		exit;
       
    63 		}
       
    64 	
       
    65 	#Could add an optimisation to this to search for the <td class="error"> tag BUT doesn't take into account the crashed tests and would need to check here the pass/fail count
       
    66 	#In addition this might lead to migration problems with Sirroco and certainly isn't appliable to developer's personal builds where we must scan each file
       
    67 	#So it's simpler to do the brute force approach and keep all implementations alike, it doesn't take long anyway
       
    68 	while ($summaryContents =~ s/href="(.*?($KMistralCoreConfFileName|$KMistralTEFFileName|$KMistralTestFrameworkFileName).*?\.html?)"//i)
       
    69 		{
       
    70 		$fileNames[$nextFileNamesIndex] = $1;
       
    71 		$nextFileNamesIndex++;
       
    72 		}
       
    73 
       
    74 	# Scan this second so we don't accidentally cut off the filenames if they are matched against Winscw runs
       
    75 	while ($summaryContents =~ s/href="(.*?($KMistrealTEFFileNameHW|$KMistrealTFFileNameHW1|$KMistrealTFFileNameHW2|$KMistrealTFFileNameHW3|$KMistrealTFFileNameHW4).*?\.html?)"//i)
       
    76 		{
       
    77 		$fileNames[$nextFileNamesIndex] = $1;
       
    78 		$nextFileNamesIndex++;
       
    79 		}
       
    80 	
       
    81 	unless ($fileNames[0])
       
    82 		{
       
    83 		print "\nERROR: No test result log files found, please ensure the -s parameter points to Mistral's TestResults.html summary page\n";	
       
    84 		exit;
       
    85 		}
       
    86 		
       
    87 	return @fileNames;
       
    88 	}
       
    89 
       
    90 # Parse the Mistral test results summary page and generate an array of TestScriptResults
       
    91 # objects which contain all the required information such as script names, test counts
       
    92 # and failures.
       
    93 # param1 - the URL of the Test Results HTML Summary page for the Mistral build 
       
    94 # returns - the array of parsed log data
       
    95 sub PopulateResultsArrayFromMistral
       
    96 	{
       
    97 	my $aTestResultsSummaryPageUrl = shift;
       
    98 	my @aResultsArray = ();
       
    99 	my $nextFreeIndexInResultsArray = 0;
       
   100 	
       
   101 	my @fileNames = GetResultFilesFromMistral($aTestResultsSummaryPageUrl);
       
   102 	foreach my $fileName (@fileNames)
       
   103 		{
       
   104 		my $testFileContents = get "$fileName";
       
   105 		unless ($testFileContents)
       
   106 			{
       
   107 			print "\nERROR: Unable to open logfile $fileName\n";
       
   108 			next;
       
   109 			}
       
   110 			
       
   111 		my $scriptResults = TestScriptResults->TestScriptResults();
       
   112 		$scriptResults->SetFilePath($fileName);		
       
   113 		if (($fileName =~ m/.*?$KMistralTEFFileName(.*?)\.html?/i) || ($fileName =~ m/.*?$KMistrealTEFFileNameHW(.*?)\.html?/i))
       
   114 			{
       
   115 			$scriptResults->SetScriptName($1);
       
   116 			if (!($testFileContents =~ m/TEST CASE SUMMARY:/i) && ($testFileContents =~ m/SUMMARY:/i))
       
   117 				{
       
   118 				# One of the old MM TEF tests which didn't use testcases
       
   119 				$scriptResults->TEFNoTestcasesTest();
       
   120 				$aResultsArray[$nextFreeIndexInResultsArray] = ScanTEFLogFileForFailures($scriptResults, \$testFileContents, 0);
       
   121 				}
       
   122 			else
       
   123 				{
       
   124 				$scriptResults->TEFTest();
       
   125 				$aResultsArray[$nextFreeIndexInResultsArray] = ScanTEFLogFileForFailures($scriptResults, \$testFileContents, 1);
       
   126 				}	
       
   127 			}
       
   128 		elsif ($fileName =~ m/.*?$KMistralCoreConfFileName(.*?)\.txt\.html?/i)
       
   129 			{
       
   130 			$scriptResults->SetScriptName($1);
       
   131 			$scriptResults->CoreConfTest();
       
   132 			$aResultsArray[$nextFreeIndexInResultsArray] = ScanCoreConfLogFileForFailures($scriptResults, \$testFileContents);
       
   133 			}
       
   134 		elsif (($fileName =~ m/.*?$KMistralTestFrameworkFileName[^\-]*?\-(.*?)\.html?/i) || ($fileName =~ m/.*?$KMistrealTFFileNameHW2(.*?)\.html?/i) || ($fileName =~ m/.*?$KMistrealTFFileNameHW3(.*?)\.html?/i) || ($fileName =~ m/.*?$KMistrealTFFileNameHW4(.*?)\.html?/i) || ($fileName =~ m/.*?$KMistrealTFFileNameHW1(.*?)\.html?/i))
       
   135 			{
       
   136 			$scriptResults->SetScriptName($1);
       
   137 			$scriptResults->TestFrameworkTest();
       
   138 			
       
   139 			$aResultsArray[$nextFreeIndexInResultsArray] = ScanTestFrameworkLogFileForFailures($scriptResults, \$testFileContents);
       
   140 			}
       
   141 		else
       
   142 			{
       
   143 			print "\nWARNING: Results file has unrecognised format - $fileName.\n";			
       
   144 			}
       
   145 		$nextFreeIndexInResultsArray++;	
       
   146 		}
       
   147 	
       
   148 	return \@aResultsArray;
       
   149 	}
       
   150 	
       
   151 
       
   152 # Walk the file path provided by the developer for his local machine, parse test logs
       
   153 #  and generate an array of TestScriptResults objects which contain all the required 
       
   154 # information such as script names, test counts and failures.
       
   155 # param1 - the pathname of a folder containing the test results
       
   156 # returns - the array of parsed log data
       
   157 sub PopulateResultsArrayFromLocalMachine
       
   158 	{
       
   159 	my $aTestResultsPath = shift;
       
   160 	my @aResultsArray = ();
       
   161 	my $nextFreeIndexInResultsArray = 0;
       
   162 
       
   163 	my @directories = ("$aTestResultsPath");
       
   164 	my @fileNames;
       
   165 	find( sub { push @fileNames, $File::Find::name if /\.html?$/ }, @directories );
       
   166 
       
   167 	foreach my $fileName (@fileNames)
       
   168 		{
       
   169 		my $testFileContents = do { local $/; open(I,"$fileName"); <I> };
       
   170 		my $scriptResults = TestScriptResults->TestScriptResults();
       
   171 		$scriptResults->SetFilePath($fileName);
       
   172 		$fileName =~ m/([^\\\/\.]*)\.[^\\\/]*\Z/;
       
   173 		$scriptResults->SetScriptName($1);
       
   174 		
       
   175 		if ($testFileContents =~ m/Core Loader Conformance Suite/)
       
   176 			{
       
   177 			$scriptResults->CoreConfTest();
       
   178 			$aResultsArray[$nextFreeIndexInResultsArray] = ScanCoreConfLogFileForFailures($scriptResults, \$testFileContents);
       
   179 			}
       
   180 		elsif ($testFileContents =~ m/TestFrameworkMain.cpp/)
       
   181 			{
       
   182 			$scriptResults->TestFrameworkTest();
       
   183 			$aResultsArray[$nextFreeIndexInResultsArray] = ScanTestFrameworkLogFileForFailures($scriptResults, \$testFileContents);
       
   184 			}
       
   185 		elsif ($testFileContents =~ m/TEF Version/)
       
   186 			{
       
   187 			if ($testFileContents =~ m/TEST CASE SUMMARY:/i)
       
   188 				{
       
   189 				$scriptResults->TEFTest();
       
   190 				$aResultsArray[$nextFreeIndexInResultsArray] = ScanTEFLogFileForFailures($scriptResults, \$testFileContents, 1);
       
   191 				}
       
   192 			else
       
   193 				{
       
   194 				# One of the old MM TEF tests which didn't use testcases
       
   195 				$scriptResults->TEFNoTestcasesTest();
       
   196 				$aResultsArray[$nextFreeIndexInResultsArray] = ScanTEFLogFileForFailures($scriptResults, \$testFileContents, 0);
       
   197 				}			
       
   198 			}
       
   199 		else
       
   200 			{
       
   201 			print "\nWARNING: Results file has unrecognised format - $fileName.\n";	
       
   202 			}
       
   203 					
       
   204 		$nextFreeIndexInResultsArray++;	
       
   205 		}
       
   206 	
       
   207 	return \@aResultsArray;
       
   208 	}
       
   209 	
       
   210 ###############################################
       
   211 ##	Test harness specific functionality
       
   212 ###############################################	
       
   213 
       
   214 # Parses a TF log file for failures, inconclusives and crashes
       
   215 # param1 - the TestScriptResults object to populate
       
   216 # param2 - reference to the contents of the log file
       
   217 # returns - the TestScriptResults object containing the parsed data
       
   218 sub ScanTestFrameworkLogFileForFailures
       
   219 	{
       
   220 	my ($aScriptResults, $aLogFileContents) = @_;
       
   221 	
       
   222 	my $testFileContents = $$aLogFileContents;
       
   223 	my $numberOfTests = 0;
       
   224 	# Search for test case results, which take the following form:
       
   225 	#04/09/2002 15:51:39:772    V   Log.cpp 736 Test Result for TSI_ICL_BTRANS_01:MM_ICL_BTRANS_I_0202_CP is PASS
       
   226 	while ($testFileContents =~ s/Test[\s]+Result[\s]+for[\s]+[\S]+:([\_|\-|\S]+)[\s]+is[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)
       
   227 		{
       
   228 		my $testId  = $1;
       
   229 	    my $result = $2;
       
   230 	    $numberOfTests++;
       
   231 		if ($result =~ /PASS/)
       
   232 			{
       
   233 			# Do nothing
       
   234 			}
       
   235 		elsif ($result =~ /INCONCLUSIVE/)
       
   236 			{
       
   237 			$aScriptResults->AddInconclusiveResult($testId);
       
   238 			}
       
   239 		else
       
   240 			{
       
   241 			# Treat all other results as failure
       
   242 			$aScriptResults->AddFailureResult($testId);
       
   243 			}
       
   244 		}
       
   245 	$aScriptResults->SetTotalTestCount($numberOfTests);
       
   246 	
       
   247 	unless ($testFileContents =~ m/Test Results Summary/)
       
   248 		{
       
   249 		# Test file summary not in the log file - the test has crashed
       
   250 		$aScriptResults->TestCrashed();
       
   251 		}
       
   252 	
       
   253 	return $aScriptResults;
       
   254 	}
       
   255 
       
   256 # Parses a TEF log file for failures, inconclusives and crashes
       
   257 # param1 - the TestScriptResults object to populate
       
   258 # param2 - reference to the contents of the log file
       
   259 # param3 - boolean whether the test is using testcases (older MM tests didn't, in which case we use the test steps)
       
   260 # returns - the TestScriptResults object containing the parsed data
       
   261 sub ScanTEFLogFileForFailures
       
   262 	{
       
   263 	my ($aScriptResults, $aLogFileContents, $aTestcasesInUse) = @_;
       
   264 	
       
   265 	my $testFileContents = $$aLogFileContents;
       
   266 	my $numberOfTests = 0;
       
   267 
       
   268 	# Search for test case results, which take the following form:
       
   269 	# 02:56:42:145 c:\mm\tsu_3gp_compose_api_te.script Line = 58 Command = END_TESTCASE MM-3GP-COMP-U-0003-CP ***TestCaseResult = PASS 
       
   270 	# Or if testcases not in use in this script file test step results, which take the following form:
       
   271 	# 14:20:51:459 c:\mm\tsu_mmf_aclnt_securedrmtestdata.script Line = 36 Command = RUN_TEST_STEP 1000 RTAUtils ImportDrmArchive c:\mm\tsu_mmf_aclnt_securedrmtestdata.ini ImportSmallWavDrmArchiveAudio ***Result = UNEXECUTED 
       
   272 	while (($testFileContents =~ s/Command[\s]+=[\s]+END\_TESTCASE[\s]+([\_|\-|\S]+)[\s]+\*\*\*TestCaseResult[\s]+=[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)
       
   273 			|| (!$aTestcasesInUse && ($testFileContents =~ s/Command[\s]+=[\s]+RUN\_TEST\_STEP[\s]+\d*[\s]+.*?[\s]+([\_|\-|\S]+)[\s]+.*?\*\*\*Result[\s]+=[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)))
       
   274 		{
       
   275 		my $testId  = $1;
       
   276 	    my $result = $2;
       
   277 	    $numberOfTests++;
       
   278 		if ($result =~ /PASS/)
       
   279 			{
       
   280 			# Do nothing
       
   281 			}
       
   282 		elsif ($result =~ /INCONCLUSIVE/)
       
   283 			{
       
   284 			$aScriptResults->AddInconclusiveResult($testId);
       
   285 			}
       
   286 		else
       
   287 			{
       
   288 			# Treat all other results as failure
       
   289 			$aScriptResults->AddFailureResult($testId);
       
   290 			}
       
   291 		}
       
   292 	$aScriptResults->SetTotalTestCount($numberOfTests);
       
   293 	
       
   294 	# Testcase scripts use TEST CASE SUMMARY, non-testcase scripts just use SUMMARY
       
   295 	unless ($testFileContents =~ m/SUMMARY:/)
       
   296 		{
       
   297 		# Test file summary not in the log file - the test has crashed
       
   298 		$aScriptResults->TestCrashed();
       
   299 		}
       
   300 	
       
   301 	return $aScriptResults;	
       
   302 	}
       
   303 
       
   304 # Parses a CoreConf log file for failures, inconclusives and crashes
       
   305 # param1 - the TestScriptResults object to populate
       
   306 # param2 - reference to the contents of the log file
       
   307 # returns - the TestScriptResults object containing the parsed data	
       
   308 sub ScanCoreConfLogFileForFailures
       
   309 	{
       
   310 	my ($aScriptResults, $aLogFileContents) = @_;
       
   311 	my $testFileContents = $$aLogFileContents;
       
   312 	
       
   313 	if ($testFileContents =~ s/\*\*\*\s*?Summary of tests executed(.*\n)*//)
       
   314 		{
       
   315 		my $numberOfTests = 0;
       
   316 
       
   317 		# Parse the summary listings
       
   318 		while($testFileContents =~ s/\*\*\*\s*?Passed tests:((.*\n)*?)\*\*\*\s*?Failed tests:.*\n((\*\*\*.*\n)*)//)
       
   319 			{
       
   320 			my $passingTests = $1;
       
   321 			my $failingTests = $3;
       
   322 			
       
   323 			# Passing tests
       
   324 			while ($passingTests =~ s/\*\*\*[\s]*?\S+[\s]*\n//)
       
   325 				{
       
   326 				$numberOfTests++;
       
   327 				}
       
   328 			
       
   329 			# Failing tests
       
   330 			while ($failingTests =~ s/\*\*\*[\s]*?(\S+)[\s]*\n//)
       
   331 				{
       
   332 				$aScriptResults->AddFailureResult($1);
       
   333 				$numberOfTests++;
       
   334 				}			
       
   335 			}
       
   336 
       
   337 		$aScriptResults->SetTotalTestCount($numberOfTests);		
       
   338 		}
       
   339 	else
       
   340 		{
       
   341 		# Test file summary not in the log file - the test has crashed
       
   342 		$aScriptResults->TestCrashed();		
       
   343 		}
       
   344 	
       
   345 	return $aScriptResults;		
       
   346 	}
       
   347 
       
   348 # Gets the test case count from a Test Execute Framework log file
       
   349 # param1 - a reference to the contents of the TEF log file
       
   350 #returns - The number of test cases in the script or -1 if the summary could not be found
       
   351 sub GetTEFTestCount
       
   352 	{
       
   353 	my $aReferenceLogContents = shift;
       
   354 	my $refContents = $$aReferenceLogContents;
       
   355 
       
   356 	if ($refContents =~ m/TEST CASE SUMMARY:(.*\n)*?.*?PASS =\s*(\d*)(.*\n)*?.*?FAIL =\s*(\d*)(.*\n)*?.*?INCONCLUSIVE =\s*(\d*)/)
       
   357 		{
       
   358 		my $result = $2 + $4 + $6;
       
   359 		return $result;
       
   360 		}
       
   361 	
       
   362 	if ($refContents =~ m/SUMMARY:(.*\n)*?.*?PASS =\s*(\d*)(.*\n)*?.*?FAIL =\s*(\d*)(.*\n)*?.*?ABORT =\s*(\d*)(.*\n)*?.*?PANIC =\s*(\d*)(.*\n)*?.*?INCONCLUSIVE =\s*(\d*)(.*\n)*?.*?UNKNOWN =\s*(\d*)(.*\n)*?.*?UNEXECUTED =\s*(\d*)/)	
       
   363 		{
       
   364 		# One of the MM tests that doesn't use testcases
       
   365 		my $result = $2 + $4 + $6 + $8 + $10 + $12 + $14;
       
   366 		return $result;
       
   367 		}									
       
   368 	
       
   369 	# Summary not found, we crashed
       
   370 	return -1;
       
   371 	}
       
   372 
       
   373 # Gets the test count from a Test Framework log file
       
   374 # param1 - a reference to the contents of the Test Framework log file
       
   375 #returns - The number of test cases in the script or -1 if the summary could not be found	
       
   376 sub GetTestFrameworkTestCount
       
   377 	{
       
   378 	my $aReferenceLogContents = shift;
       
   379 	my $refContents = $$aReferenceLogContents;
       
   380 	
       
   381 	unless ($refContents =~ m/Test Results Summary(.*\n)*?.*?Total\s*:(\d*)\s*\n/)
       
   382 		{
       
   383 		# Summary not found, we crashed
       
   384 		return -1;
       
   385 		}
       
   386 	return $2;
       
   387 	}
       
   388 
       
   389 # Gets the test count from an OpenMAX IL Core Conformance log file
       
   390 # param1 - a reference to the contents of the Core Conformance log file
       
   391 #returns - The number of test cases in the script or -1 if the summary could not be found	
       
   392 sub GetCoreConfTestCount
       
   393 	{
       
   394 	my $aReferenceLogContents = shift;
       
   395 	my $refContents = $$aReferenceLogContents;
       
   396 	
       
   397 	unless ($refContents =~ m/\*\*\*\s*Summary of tests executed(.*\n)*?\*\*\*\s*Total :\s*(\d*)\s*\n/)
       
   398 		{
       
   399 		# Summary not found, we crashed
       
   400 		return -1;
       
   401 		}
       
   402 	return $2;
       
   403 	}
       
   404 
       
   405 # Scans a TEF log looking for the test specified and checks if it returned inconclusive
       
   406 # param1 - the test name
       
   407 # param2 - reference to the contents of the log file, the test case result is removed from the argument if passed by ref
       
   408 # param3 - whether the TEF script uses testcases
       
   409 # returns - 1 if it returned inconclusive, 0 otherwise	
       
   410 sub MatchingTEFInconclusiveResult	
       
   411 	{
       
   412 	my $aInconclusive = shift;
       
   413 	my $aReferenceLogContents = shift;
       
   414 	my $aTestcasesInUse = shift;
       
   415 	my $refContents = $$aReferenceLogContents;
       
   416 	if ($aTestcasesInUse)
       
   417 		{
       
   418 		if ($refContents =~ s/Command[\s]+=[\s]+END\_TESTCASE[\s]+$aInconclusive[\s]+\*\*\*TestCaseResult[\s]+=[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)
       
   419 			{
       
   420 			if ($1 eq "INCONCLUSIVE")
       
   421 				{
       
   422 				return 1;
       
   423 				}
       
   424 			}
       
   425 		}
       
   426 	else
       
   427 		{
       
   428 		if ($refContents =~ s/Command[\s]+=[\s]+RUN\_TEST\_STEP[\s]+\d*[\s]+.*?[\s]+$aInconclusive[\s]+.*?\*\*\*Result[\s]+=[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)
       
   429 			{
       
   430 			if ($1 eq "INCONCLUSIVE")
       
   431 				{
       
   432 				return 1;
       
   433 				}
       
   434 			}
       
   435 		}
       
   436 	return 0;
       
   437 	}
       
   438 
       
   439 # Scans a TestFramework log looking for the test specified and checks if it returned inconclusive
       
   440 # param1 - the test name
       
   441 # param2 - reference to the contents of the log file, the test case result is removed from the argument if passed by ref
       
   442 # returns - 1 if it returned inconclusive, 0 otherwise		
       
   443 sub MatchingTFInconclusiveResult 
       
   444 	{
       
   445 	my $aInconclusive = shift;
       
   446 	my $aReferenceLogContents = shift;
       
   447 	my $refContents = $$aReferenceLogContents;
       
   448 	if ($refContents =~ s/Test[\s]+Result[\s]+for[\s]+[\S]+:$aInconclusive[\s]+is[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)
       
   449 		{
       
   450 		if ($1 eq "INCONCLUSIVE")
       
   451 			{
       
   452 			return 1;
       
   453 			}
       
   454 		}
       
   455 	return 0;
       
   456 	}
       
   457 
       
   458 # Scans a TEF log looking for the test specified and checks if it returned an error
       
   459 # param1 - the test name
       
   460 # param2 - reference to the contents of the log file, the test case result is removed from the argument if passed by ref
       
   461 # param3 - whether the TEF script uses testcases
       
   462 # returns - 1 if it returned an error, 0 otherwise		
       
   463 sub MatchingTEFErrorResult 
       
   464 	{
       
   465 	my $aFail = shift;
       
   466 	my $aReferenceLogContents = shift;
       
   467 	my $aTestcasesInUse = shift;
       
   468 	my $refContents = $$aReferenceLogContents;
       
   469 	
       
   470 	if ($aTestcasesInUse)
       
   471 		{
       
   472 		if (not $refContents =~ s/Command[\s]+=[\s]+END\_TESTCASE[\s]+$aFail[\s]+\*\*\*TestCaseResult[\s]+=[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)
       
   473 			{
       
   474 			return 0;
       
   475 			}
       
   476 	
       
   477 		if (($1 eq "PASS") || ($1 eq "INCONCLUSIVE"))
       
   478 			{
       
   479 			return 0;
       
   480 			}
       
   481 		}
       
   482 	else
       
   483 		{
       
   484 		if (not $refContents =~ s/Command[\s]+=[\s]+RUN\_TEST\_STEP[\s]+\d*[\s]+.*?[\s]+$aFail[\s]+.*?\*\*\*Result[\s]+=[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)
       
   485 			{
       
   486 			return 0;
       
   487 			}
       
   488 	
       
   489 		if (($1 eq "PASS") || ($1 eq "INCONCLUSIVE"))
       
   490 			{
       
   491 			return 0;
       
   492 			}
       
   493 		}
       
   494 		
       
   495 	return 1;
       
   496 	}	
       
   497 	
       
   498 # Scans a TestFramework log looking for the test specified and checks if it returned an error
       
   499 # param1 - the test name
       
   500 # param2 - reference to the contents of the log file, the test case result is removed from the argument if passed by ref
       
   501 # returns - 1 if it returned an error, 0 otherwise		
       
   502 sub MatchingTFErrorResult 
       
   503 	{
       
   504 	my $aFail = shift;
       
   505 	my $aReferenceLogContents = shift;
       
   506 	my $refContents = $$aReferenceLogContents;
       
   507 	if (not $refContents =~ s/Test[\s]+Result[\s]+for[\s]+[\S]+:$aFail[\s]+is[\s]+([\_|\-|\S]+)[\s]*\<\/font\>//)
       
   508 		{
       
   509 		return 0;
       
   510 		}
       
   511 	
       
   512 	if (($1 eq "PASS") || ($1 eq "INCONCLUSIVE"))
       
   513 		{
       
   514 		return 0;
       
   515 		}
       
   516 		
       
   517 	return 1;
       
   518 	}	
       
   519 	
       
   520 # N.B. VERY IMPORTANT that the log file is passed by reference.  Core conf scripts can include numerous
       
   521 # different tests that use the same test name so to avoid false positives from this function the 
       
   522 # substitution done in the comparison MUST affect the caller's copy of the log file.
       
   523 sub MatchingCoreConfErrorResult
       
   524 	{	
       
   525 	my $aFail = shift;
       
   526 	my $aReferenceLogContents = shift;
       
   527 	my $refContents = $$aReferenceLogContents;
       
   528 	
       
   529 	if ($refContents =~ s/\*\*\*[\s]*$aFail[\s]*FAILED//)
       
   530 		{
       
   531 		return 1;
       
   532 		}
       
   533 
       
   534 	return 0;	
       
   535 	}
       
   536 	
       
   537 ###############################################		
       
   538 ##	Failure comparison functions
       
   539 ###############################################		
       
   540 
       
   541 # The analysis takes an array of TestScriptResults, each storing the results of a test script's log file.
       
   542 # It processes this list in stages looking for any scripts with errors and trying to match them against
       
   543 # entries in a Known Failure sheet and/or comparison reference build.  Whenever a match is found
       
   544 # the error is removed from the TestScriptResults object, these essentially act as an object containing
       
   545 # unresolved errors.  When errors are matched their details are added to the corresponding text 
       
   546 # variables at the top of this file (e.g. iKnownFails).
       
   547 sub AnalyseFailures
       
   548 	{
       
   549 	my ($aKFSheetLocation, $aReferenceMistralURL, $aIgnoreFailsNotInRef, $aResultsRef, $aKfPlatforms) = @_;
       
   550 
       
   551 	my @results = @$aResultsRef;
       
   552 	
       
   553 	my $refContents = undef;
       
   554 	if ($aReferenceMistralURL)
       
   555 		{
       
   556 		$refContents = get "$aReferenceMistralURL"; # Returns undef if failure
       
   557 		unless ($refContents)
       
   558 			{
       
   559 			print "\nERROR: Unable to retrieve reference summary file from $aReferenceMistralURL\n";
       
   560 			exit;
       
   561 			}		
       
   562 		}
       
   563 	
       
   564 	my $kfSheetContents = undef;
       
   565 	if ($aKFSheetLocation)
       
   566 		{
       
   567 		unless ($aKFSheetLocation =~ m/\.xml\Z/i)
       
   568 			{
       
   569 			print "\nERROR: KF sheet ($aKFSheetLocation) does not appear to be in XML format, you should save the Excel worksheet as XML Spreadsheet 2003 format for input to this script.\n";	
       
   570 			exit;
       
   571 			}		
       
   572 		$kfSheetContents = do { local $/; open(I,"$aKFSheetLocation"); <I> };
       
   573 		unless ($kfSheetContents)
       
   574 			{
       
   575 			print "\nERROR: Unable to open KF sheet at $aKFSheetLocation\n";	
       
   576 			exit;			
       
   577 			}
       
   578 		}
       
   579 		
       
   580 	foreach my $scriptResults (@results)
       
   581 		{
       
   582 		my $scriptName = $scriptResults->ScriptName();
       
   583 		
       
   584 		my $referenceResults = undef;
       
   585 		
       
   586 		# If a reference build was provided, find the corresponding log file
       
   587 		if ($refContents)
       
   588 			{
       
   589 			# We use substitution here because some of the coreconf test scripts
       
   590 			# have the same script name.  This ensures we don't keep referencing
       
   591 			# against the same copy.  We cannot do the comparison on the script 
       
   592 			# path because this isn't resilient to adding new tests or cross domain 
       
   593 			# comparisons.
       
   594 			# N.B. This assumes the test list ordering remains the same.
       
   595 			# N.B. The optional .txt is for Core Conf tests
       
   596 			$refContents =~ s/href="(.*?$scriptName(\.txt)?(\.script)?\.html?)"//;
       
   597 			my $file = $1;
       
   598 			if ($file eq undef)
       
   599 				{
       
   600 				if ($aIgnoreFailsNotInRef)
       
   601 					{
       
   602 					next;
       
   603 					}
       
   604 				print "\nWARNING: Unable to find $scriptName in Reference Build\n";	
       
   605 				}
       
   606 			else
       
   607 				{
       
   608 				$referenceResults = get "$file";	# returns undef on failure
       
   609 				unless ($referenceResults)
       
   610 					{
       
   611 					print "\nWARNING: Unable to open $scriptName ($file) in Reference Build\n";			
       
   612 					}
       
   613 				}
       
   614 			}
       
   615 		
       
   616 		my $refTestCrashed;
       
   617 		# Check the test count hasn't decreased
       
   618 		if ($referenceResults)
       
   619 			{
       
   620 			$refTestCrashed = CheckTestCount($scriptResults, \$referenceResults);
       
   621 			}
       
   622 			
       
   623 		if (not $scriptResults->AnyFailures())
       
   624 			{
       
   625 			# No errors so move onto the next
       
   626 			next;
       
   627 			}
       
   628 		
       
   629 		if ($kfSheetContents)
       
   630 			{
       
   631 			ResolveFailuresAgainstKFSheet($scriptResults, \$kfSheetContents, $aKfPlatforms); 
       
   632 		
       
   633 			if (not $scriptResults->AnyFailures())
       
   634 				{
       
   635 				# All errors resolved against KF sheet so move onto the next
       
   636 				next;
       
   637 				}
       
   638 			}	
       
   639 		
       
   640 		if ($referenceResults)
       
   641 			{
       
   642 			ResolveFailuresAgainstReferenceRun($scriptResults, $refTestCrashed, \$referenceResults);
       
   643 			
       
   644 			if (not $scriptResults->AnyFailures())
       
   645 				{
       
   646 				# All errors resolved against reference run so move onto the next
       
   647 				next;
       
   648 				}			
       
   649 			}
       
   650 		
       
   651 		# Unknown failures
       
   652 		$iUnknownFails = $iUnknownFails . "\n$scriptName\n";
       
   653 		
       
   654 		my $inconText;
       
   655 		my @inconclusives = $scriptResults->Inconclusives();
       
   656 		foreach my $inconclusive (@inconclusives)
       
   657 			{
       
   658 			$inconText = $inconText . "$inconclusive\n";
       
   659 			}
       
   660 		my $failText;
       
   661 		my @failures = $scriptResults->Failures();
       
   662 		foreach my $failure (@failures)
       
   663 			{
       
   664 			$failText = $failText . "$failure\n";
       
   665 			}	
       
   666 			
       
   667 		if ($inconText)
       
   668 			{
       
   669 			$iUnknownFails = $iUnknownFails . "INCONCLUSIVES:\n$inconText";
       
   670 			}
       
   671 		if ($failText)
       
   672 			{
       
   673 			$iUnknownFails = $iUnknownFails . "FAILS:\n$failText";
       
   674 			}
       
   675 		if ($scriptResults->DidItCrash())	
       
   676 			{
       
   677 			$iUnknownFails = $iUnknownFails . "CRASHED\n";
       
   678 			}
       
   679 		}	
       
   680 	
       
   681 	}
       
   682 
       
   683 # Will compare the test count of the test in question against the equivalent result from a reference build's log
       
   684 # to detect if there has been a reduction in the total number of tests run as part of the script, unless that script 
       
   685 # has crashed.  As a side effect the return value indicates whether the test in question crashed or not (saves
       
   686 # having to scan it twice).
       
   687 # param1 - the log results to compare against the reference build's run
       
   688 # param2 - the contents of the reference build's corresponding test log
       
   689 # returns = 1 if the reference script crashed and we were unable to compare the counts, 0 otherwise
       
   690 sub CheckTestCount
       
   691 	{
       
   692 	my ($aTestResultsObject, $aReferenceLogContents) = @_;
       
   693 	
       
   694 	my $testHarness = $aTestResultsObject->TestHarness();
       
   695 	my $refTestCount;
       
   696 	if (($testHarness eq $TestScriptResults::KTEFTest) || ($testHarness eq $TestScriptResults::KTEFNoTestcasesTest))
       
   697 		{
       
   698 		$refTestCount = GetTEFTestCount($aReferenceLogContents);
       
   699 		}
       
   700 	elsif ($testHarness eq $TestScriptResults::KTestFrameworkTest)
       
   701 		{
       
   702 		$refTestCount = GetTestFrameworkTestCount($aReferenceLogContents);
       
   703 		}
       
   704 	else
       
   705 		{
       
   706 		$refTestCount = GetCoreConfTestCount($aReferenceLogContents);
       
   707 		}
       
   708 	
       
   709 	if ($refTestCount < 0)
       
   710 		{
       
   711 		# Reference test crashed
       
   712 		unless ($aTestResultsObject->DidItCrash())
       
   713 			{
       
   714 			my $scriptName = $aTestResultsObject->ScriptName();
       
   715 			print "\nWARNING: $scriptName crashed in the reference build, unable to compare test counts\n";
       
   716 			}
       
   717 		return 1;
       
   718 		}
       
   719 	
       
   720 	my $testCount = $aTestResultsObject->TotalTestCount;
       
   721 	if ($testCount < $refTestCount)
       
   722 		{
       
   723 		unless ($aTestResultsObject->DidItCrash())
       
   724 			{
       
   725 			my $testName = $aTestResultsObject->ScriptName();
       
   726 			$iMissingTests = $iMissingTests . "$testName  Previous = $refTestCount, Current = $testCount\n"; 	
       
   727 			}
       
   728 		}
       
   729 	return 0;	
       
   730 	}	
       
   731 
       
   732 # Will scan the Known Failure sheet for any entries indicating if the failures,inconclusives and/or crash
       
   733 # witnessed in the script in question are already known. If so these will be appended to the known failures list
       
   734 # and removed from the TestScriptResults object in question. If matching entries were found but existed for
       
   735 # other codelines then this information is stored but the failures are not removed from the TestScriptResults 
       
   736 # object.
       
   737 # param1 - TestScriptResults object for the script with failures
       
   738 # param2 - the contents of the known failure sheet
       
   739 # param3 - the array of platform entries in the known failure sheet that are applicable to this run
       
   740 sub ResolveFailuresAgainstKFSheet
       
   741 	{
       
   742 	my ($aScriptWithProblems, $aKfSheetContents, $aKfPlatforms) = @_;
       
   743 	my $kfSheetContents = $$aKfSheetContents;
       
   744 	my $scriptName = $aScriptWithProblems->ScriptName();
       
   745 	
       
   746 	my @kFApplicablePlatforms;
       
   747 	if ($aKfPlatforms)
       
   748 		{
       
   749 		# Will error if undef
       
   750 		@kFApplicablePlatforms = @$aKfPlatforms;
       
   751 		}
       
   752 
       
   753 	# Modified version of the KF Sheet contents, at the end of this function it will contain the Rows from the KF Sheet with any that correspond to the current test script stripped out.
       
   754 	# This is a by product of the fact that we inspect each row one at a time looking for any that are relevant, trying to do a global search results in potentially error prone and difficult to maintain
       
   755 	# regexs.  And in reality underneath Perl shouldn't be doing that much in the way of optimisation versus this approach.
       
   756 	my $wipKfSheet;
       
   757 	my $candidatesForOtherPlatforms;
       
   758 	my $foundSamePlatFails;
       
   759 	my $foundSamePlatInconcs;
       
   760 	my $foundSamePlatCrash;
       
   761 	while ($kfSheetContents =~ s/<Row((.|\n)*?>)((.|\n)*?)<\/Row>//i)
       
   762 		{
       
   763 		my $row = $3;
       
   764 		# Optimisation
       
   765 		unless ($row =~ m/$scriptName/i)
       
   766 			{
       
   767 			$wipKfSheet = $wipKfSheet . "<Row>$row<\/Row>";
       
   768 			next;
       
   769 			}
       
   770 		
       
   771 		# None of the cells prior to the 'Scriptname' named cell are of any interest, now verify this row is actually for 
       
   772 		# this test script and we didn't pick the hit up off the entries for one of the other fields, e.g. Remarks
       
   773 		my $applicable;
       
   774 		while ($row =~ s/(<Cell(.|\n)*?<\/Cell>)//i)
       
   775 			{
       
   776 			my $cell = $1;
       
   777 			if ($cell =~ m/<NamedCell\s*\n?\s*ss:Name="Scriptname\d*"\//i)
       
   778 				{
       
   779 				# Named field we're looking for
       
   780 				if ($cell =~ m/$scriptName/i)
       
   781 					{
       
   782 					$applicable = 1;
       
   783 					last;
       
   784 					}
       
   785 				else
       
   786 					{
       
   787 					$wipKfSheet = $wipKfSheet . "<Row>$cell\n$row<\/Row>";	# This entry isn't applicable to us, reinsert it into the KF sheet
       
   788 					last;
       
   789 					}
       
   790 				}
       
   791 			}
       
   792 		unless ($applicable)
       
   793 			{
       
   794 			next;
       
   795 			}
       
   796 		
       
   797 		# We are now dealing with a Row corresponding to the script in question
       
   798 		# So pull out the relevant named cells contents
       
   799 		my $crash;
       
   800 		my $fails;
       
   801 		my $inconclusives;
       
   802 		my $targets;
       
   803 		while ($row =~ s/(<Cell(.|\n)*?<\/Cell>)//i)
       
   804 			{
       
   805 			my $cell = $1;
       
   806 			if ($cell =~ m/<NamedCell\s*\n?\s*ss:Name="CrashedStatus\d*"\//i)
       
   807 				{
       
   808 				$crash = $cell;
       
   809 				}
       
   810 			elsif ($cell =~ m/<NamedCell\s*\n?\s*ss:Name="Fails\d*"\//i)
       
   811 				{
       
   812 				$fails = $cell;			
       
   813 				}
       
   814 			elsif ($cell =~ m/<NamedCell\s*\n?\s*ss:Name="Inconclusives\d*"\//i)
       
   815 				{
       
   816 				$inconclusives = $cell;			
       
   817 				}
       
   818 			elsif ($cell =~ m/<NamedCell\s*\n?\s*ss:Name="Platforms\d*"\//i)
       
   819 				{
       
   820 				$targets = $cell;			
       
   821 				}				
       
   822 			}
       
   823 			
       
   824 		my $platformMatched;
       
   825 		foreach my $platform (@kFApplicablePlatforms)
       
   826 			{
       
   827 			unless (($targets =~ m/$platform&#10;/i) || ($targets =~ m/$platform<\/Data>/i))	# To ensure for example that All isn't picked up by an All Winscw entry
       
   828 				{
       
   829 				next;	# Platform not found in the entry
       
   830 				}		
       
   831 			$platformMatched = 1;
       
   832 
       
   833 			if (($aScriptWithProblems->DidItCrash()) && ($crash =~ m/Crashed/i))
       
   834 				{
       
   835 				$foundSamePlatCrash = 1;
       
   836 				$aScriptWithProblems->ResetCrashed();
       
   837 				}
       
   838 				
       
   839 			if ($fails)
       
   840 				{
       
   841 				my @failures = $aScriptWithProblems->Failures();
       
   842 				$aScriptWithProblems->ResetFailures();
       
   843 				foreach my $failure (@failures)
       
   844 					{
       
   845 					if (($fails =~ m/$failure/i) || ($fails =~ m/>ALL<\/Data>/))
       
   846 						{
       
   847 						$foundSamePlatFails = $foundSamePlatFails . "$failure\n";
       
   848 						}
       
   849 					else
       
   850 						{
       
   851 						
       
   852 						$aScriptWithProblems->AddFailureResult($failure);
       
   853 						}
       
   854 					}
       
   855 				}
       
   856 
       
   857 			if ($inconclusives)
       
   858 				{
       
   859 				my @incons = $aScriptWithProblems->Inconclusives();
       
   860 				$aScriptWithProblems->ResetInconclusives();
       
   861 				foreach my $incon (@incons)
       
   862 					{
       
   863 					if (($inconclusives =~ m/$incon/i) || ($inconclusives =~ m/>ALL<\/Data>/))
       
   864 						{
       
   865 						$foundSamePlatInconcs = $foundSamePlatInconcs . "$incon\n";
       
   866 						}
       
   867 					else
       
   868 						{
       
   869 						$aScriptWithProblems->AddInconclusiveResult($incon);
       
   870 						}
       
   871 					}
       
   872 				}
       
   873 			}	# End of platform matching loop
       
   874 		
       
   875 		unless ($platformMatched)
       
   876 			{
       
   877 			# The row entry did not match any of the applicable platforms.  We need to keep checking for more appropriate rows.
       
   878 			# However, if after the KF Sheet has been parsed we still have unknown errors, we need to compare against these rows as well
       
   879 			# in case the issue has been seen on other platforms.
       
   880 	
       
   881 			$candidatesForOtherPlatforms = $candidatesForOtherPlatforms . "<Row>$crash$fails$inconclusives<\/Row>";
       
   882 			}
       
   883 			
       
   884 		}	# End of row scanning
       
   885 	
       
   886 
       
   887 	my $foundOtherPlatFails;
       
   888 	my $foundOtherPlatInconcs;
       
   889 	my $foundOtherPlatCrash;	
       
   890 	if ($aScriptWithProblems->AnyFailures())	
       
   891 		{
       
   892 		# Failures remain, potentially matched against the rows for other platforms
       
   893 		
       
   894 		while ($candidatesForOtherPlatforms =~ s/<Row>((.|\n)*?)<\/Row>//i)
       
   895 			{
       
   896 			my $row = $1;
       
   897 			my $crash;
       
   898 			my $fails;
       
   899 			my $inconclusives;
       
   900 			while ($row =~ s/(<Cell(.|\n)*?<\/Cell>)//i)
       
   901 				{
       
   902 				my $cell = $1;
       
   903 				if ($cell =~ m/<NamedCell\s*\n?\s*ss:Name="CrashedStatus\d*"\//i)
       
   904 					{
       
   905 					$crash = $cell;
       
   906 					}
       
   907 				elsif ($cell =~ m/<NamedCell\s*\n?\s*ss:Name="Fails\d*"\//i)
       
   908 					{
       
   909 					$fails = $cell;
       
   910 					}
       
   911 				elsif ($cell =~ m/<NamedCell\s*\n?\s*ss:Name="Inconclusives\d*"\//i)
       
   912 					{
       
   913 					$inconclusives = $cell;
       
   914 					}					
       
   915 				}	# End of stripping out content details
       
   916 			
       
   917 			if (($aScriptWithProblems->DidItCrash()) && ($crash =~ m/Crashed<\/Data>/i))
       
   918 				{
       
   919 				$foundOtherPlatCrash = 1;
       
   920 				}
       
   921 				
       
   922 			if ($fails)
       
   923 				{
       
   924 				my @failures = $aScriptWithProblems->Failures();
       
   925 				foreach my $failure (@failures)
       
   926 					{
       
   927 					if (($fails =~ m/$failure/i) || ($fails =~ m/>ALL<\/Data>/))
       
   928 						{
       
   929 						$foundOtherPlatFails = $foundOtherPlatFails . "$failure\n";
       
   930 						}
       
   931 					}
       
   932 				}
       
   933 
       
   934 			if ($inconclusives)
       
   935 				{
       
   936 				my @incons = $aScriptWithProblems->Inconclusives();
       
   937 				foreach my $incon (@incons)
       
   938 					{
       
   939 					if (($inconclusives =~ m/$incon/i) || ($inconclusives =~ m/>ALL<\/Data>/))
       
   940 						{
       
   941 						$foundOtherPlatInconcs = $foundOtherPlatInconcs . "$incon\n";
       
   942 						}
       
   943 					}
       
   944 				}
       
   945 				
       
   946 			}	# End of cross-platform candidate matchine
       
   947 		}	# End of dealing with potential cross-platform matches
       
   948 
       
   949 	# Output known failures
       
   950 	if ($foundSamePlatFails || $foundSamePlatInconcs || $foundSamePlatCrash)
       
   951 		{
       
   952 		$iKnownFails = $iKnownFails . "\n$scriptName\n";
       
   953 		}
       
   954 	if ($foundSamePlatInconcs)
       
   955 		{
       
   956 		$iKnownFails = $iKnownFails . "INCONCLUSIVES:\n$foundSamePlatInconcs";
       
   957 		}
       
   958 	if ($foundSamePlatFails)
       
   959 		{
       
   960 		$iKnownFails = $iKnownFails . "FAILS:\n$foundSamePlatFails";
       
   961 		}
       
   962 	if ($foundSamePlatCrash)
       
   963 		{
       
   964 		$iKnownFails = $iKnownFails . "CRASHED\n";
       
   965 		}		
       
   966 	
       
   967 	# Output matches found only in other test platforms
       
   968 	if ($foundOtherPlatFails || $foundOtherPlatInconcs || $foundOtherPlatCrash)
       
   969 		{
       
   970 		$iUnknownFailsButKnownInOtherCodelines = $iUnknownFailsButKnownInOtherCodelines .  "\n$scriptName\n";
       
   971 		}
       
   972 	if ($foundOtherPlatInconcs)
       
   973 		{
       
   974 		$iUnknownFailsButKnownInOtherCodelines = $iUnknownFailsButKnownInOtherCodelines . "INCONCLUSIVES:\n$foundOtherPlatInconcs";
       
   975 		}
       
   976 	if ($foundOtherPlatFails)
       
   977 		{
       
   978 		$iUnknownFailsButKnownInOtherCodelines = $iUnknownFailsButKnownInOtherCodelines . "FAILS:\n$foundOtherPlatFails";
       
   979 		}
       
   980 	if ($foundOtherPlatCrash)
       
   981 		{
       
   982 		$iUnknownFailsButKnownInOtherCodelines = $iUnknownFailsButKnownInOtherCodelines . "CRASHED\n";
       
   983 		}
       
   984 		
       
   985 	$aKfSheetContents = $wipKfSheet;
       
   986 	}
       
   987 
       
   988 
       
   989 # Takes the corresponding log file from the reference build and test for a failing script and
       
   990 # compare it to see if the failures match.  If so this information is stored and the matching
       
   991 # failures removed from the TestScriptResults object.
       
   992 # param1 - TestScriptResults object for the script with failures
       
   993 # param2 - boolean whether the test crashed in the reference build and test
       
   994 # param3 - the contents of the corresponding log file from the reference build
       
   995 sub ResolveFailuresAgainstReferenceRun
       
   996 	{
       
   997 	my $aReferenceTestResults = shift;
       
   998 	my $aRefTestCrashed = shift;
       
   999 	my $aReferenceLogContents = shift;
       
  1000 	my $refContents = $$aReferenceLogContents;	
       
  1001 
       
  1002 	my $scriptName = $aReferenceTestResults->ScriptName();
       
  1003 	my $testHarness = $aReferenceTestResults->TestHarness();
       
  1004 	
       
  1005 	my $inconText;
       
  1006 	my @inconclusives = $aReferenceTestResults->Inconclusives();
       
  1007 	$aReferenceTestResults->ResetInconclusives();
       
  1008 	foreach my $inconclusive (@inconclusives)
       
  1009 		{
       
  1010 		if (($testHarness eq $TestScriptResults::KTEFTest) || ($testHarness eq $TestScriptResults::KTEFNoTestcasesTest))
       
  1011 			{
       
  1012 			my $testcasesInUse = 0;
       
  1013 			if ($testHarness eq $TestScriptResults::KTEFTest)
       
  1014 				{
       
  1015 				$testcasesInUse = 1;
       
  1016 				}
       
  1017 			if (MatchingTEFInconclusiveResult($inconclusive, \$refContents, $testcasesInUse))
       
  1018 				{
       
  1019 				$inconText = $inconText . "$inconclusive\n";
       
  1020 				}
       
  1021 			else
       
  1022 				{
       
  1023 				$aReferenceTestResults->AddInconclusiveResult($inconclusive);
       
  1024 				}
       
  1025 			}
       
  1026 		elsif ($testHarness eq $TestScriptResults::KTestFrameworkTest)
       
  1027 			{
       
  1028 			if (MatchingTFInconclusiveResult($inconclusive, \$refContents))
       
  1029 				{
       
  1030 				$inconText = $inconText . "$inconclusive\n";
       
  1031 				}
       
  1032 			else
       
  1033 				{
       
  1034 				$aReferenceTestResults->AddInconclusiveResult($inconclusive);			
       
  1035 				}			
       
  1036 			}
       
  1037 		# Core Conf tests have no comprehension of inconclusive
       
  1038 		}
       
  1039 			
       
  1040 	my $failText;
       
  1041 	my @failures = $aReferenceTestResults->Failures();
       
  1042 	$aReferenceTestResults->ResetFailures();
       
  1043 	foreach my $failure (@failures)
       
  1044 		{
       
  1045 		if (($testHarness eq $TestScriptResults::KTEFTest) || ($testHarness eq $TestScriptResults::KTEFNoTestcasesTest))
       
  1046 			{
       
  1047 			my $testcasesInUse = 0;
       
  1048 			if ($testHarness eq $TestScriptResults::KTEFTest)
       
  1049 				{
       
  1050 				$testcasesInUse = 1;
       
  1051 				}
       
  1052 			if (MatchingTEFErrorResult($failure, \$refContents, $testcasesInUse))
       
  1053 				{
       
  1054 				$failText = $failText . "$failure\n";
       
  1055 				}
       
  1056 			else
       
  1057 				{
       
  1058 				$aReferenceTestResults->AddFailureResult($failure);
       
  1059 				}
       
  1060 			}
       
  1061 		elsif ($testHarness eq $TestScriptResults::KTestFrameworkTest)
       
  1062 			{
       
  1063 			if (MatchingTFErrorResult($failure, \$refContents))
       
  1064 				{
       
  1065 				$failText = $failText . "$failure\n";
       
  1066 				}
       
  1067 			else
       
  1068 				{
       
  1069 				$aReferenceTestResults->AddFailureResult($failure);
       
  1070 				}			
       
  1071 			}
       
  1072 		else
       
  1073 			{
       
  1074 			# Core Conf 
       
  1075 			if (MatchingCoreConfErrorResult($failure, \$refContents))
       
  1076 				{
       
  1077 				$failText = $failText . "$failure\n";
       
  1078 				}
       
  1079 			else
       
  1080 				{
       
  1081 				$aReferenceTestResults->AddFailureResult($failure);
       
  1082 				}			
       
  1083 			}
       
  1084 		}
       
  1085 
       
  1086 	my $bothCrashed;
       
  1087 	if (($aReferenceTestResults->DidItCrash()) && $aRefTestCrashed)
       
  1088 		{
       
  1089 		$bothCrashed = 1;
       
  1090 		$aReferenceTestResults->ResetCrashed();
       
  1091 		}
       
  1092 	
       
  1093 	if ($inconText || $failText || $bothCrashed)
       
  1094 		{
       
  1095 		$iUnknownFailsButKnownInRef = $iUnknownFailsButKnownInRef . "\n$scriptName\n";
       
  1096 		}
       
  1097 	
       
  1098 	if 	($inconText)
       
  1099 		{
       
  1100 		$iUnknownFailsButKnownInRef = $iUnknownFailsButKnownInRef . "INCONCLUSIVES:\n$inconText";
       
  1101 		}
       
  1102 	if ($failText)
       
  1103 		{
       
  1104 		$iUnknownFailsButKnownInRef = $iUnknownFailsButKnownInRef . "FAILS:\n$failText";
       
  1105 		}
       
  1106 	if ($bothCrashed)
       
  1107 		{
       
  1108 		$iUnknownFailsButKnownInRef = $iUnknownFailsButKnownInRef . "CRASHED\n";
       
  1109 		}
       
  1110 	}
       
  1111 	
       
  1112 ###############################################
       
  1113 ##	Utility functions
       
  1114 ###############################################	
       
  1115 
       
  1116 sub PrintHelp
       
  1117 	{
       
  1118 	print "\n\nResultsComparison.pl -m Mode -s Results_source [-k Known_failure_sheet_path -c Codeline -p Platform] [-r Mistral_comparison_job_url] [-i] [-v]\n\n";
       
  1119 	print "  -m = Mode of operation, specify the source of the results that you are\n";
       
  1120 	print "    comparing. Currently supported modes: Mistral, Local\n\n";
       
  1121 	print "  -s = Source of the results, mode dependant:\n";
       
  1122 	print "      (i) Mistral = The URL of the test results HTML summary page\n";
       
  1123 	print "      (ii) Local = The pathname of a folder containing the test log files\n\n";
       
  1124 	print "  -k = Pathname of the KF sheet, this should be exported as an XML spreadsheet\n";
       
  1125 	print "    from Excel\n\n";
       
  1126 	print "  -r = Reference Mistral build, the URL of the test results HTML summary page.\n";
       
  1127 	print "    This can be used in addition or in place of the Known Failure sheet\n\n";
       
  1128 	print "  -i = Ignore test failures in scripts not found in the Reference Mistral build\n\n";
       
  1129 	print "  -c = An index indicating the codeline used in the test run, only used in\n";
       
  1130 	print "    conjunction with a KF sheet. Possible values: TB92, TB101, TB102\n\n";	
       
  1131 	print "  -p = An index indicating the platform the test run is from, only used in\n";
       
  1132 	print "    conjunction with a KF sheet. Possible values: Winscw, H6, H4 WDP,\n";
       
  1133 	print "    NaviEngine\n\n";
       
  1134 	print "  -v = Verbose output\n\n";
       
  1135 	}
       
  1136 	
       
  1137 ###############################################
       
  1138 ##	Main processing loop
       
  1139 ###############################################		
       
  1140 
       
  1141 # Read in parameters
       
  1142 my %aParams;
       
  1143 getopts('ihvm:s:k:r:c:p:', \%aParams);
       
  1144 if ($aParams{h})
       
  1145 	{
       
  1146 	PrintHelp();
       
  1147 	exit;
       
  1148 	}
       
  1149 
       
  1150 $iVerbose = $aParams{v};
       
  1151 	
       
  1152 # The mode affects where we get the source files from and nothing else.
       
  1153 my @runResults;
       
  1154 if ($aParams{m} =~ m/\AMistral\Z/i)
       
  1155 	{
       
  1156 	@runResults = @{PopulateResultsArrayFromMistral($aParams{s})};	
       
  1157 	}
       
  1158 elsif ($aParams{m} =~ m/\ALocal\Z/i)
       
  1159 	{
       
  1160 	@runResults = @{PopulateResultsArrayFromLocalMachine($aParams{s})};	
       
  1161 	}
       
  1162 else
       
  1163 	{
       
  1164 	print "\nERROR: Operation mode absent or not recognised.\n";
       
  1165 	PrintHelp();
       
  1166 	exit;
       
  1167 	}
       
  1168 	
       
  1169 my @kfPlatforms;
       
  1170 if ($aParams{k})
       
  1171 	{
       
  1172 	$kfPlatforms[0] = "All";
       
  1173 	
       
  1174 	# KF sheet in use, codeline and platform arguments are required in order to search for matching failures
       
  1175 	my $codeline = $aParams{c};
       
  1176 	my $platform = $aParams{p};
       
  1177 	unless (($codeline eq "TB92") || ($codeline eq "TB101") || ($codeline eq "TB102"))
       
  1178 		{
       
  1179 		print "\nERROR: The codeline specified was not recognised, supported options: TB92, TB101, TB102.\n";
       
  1180 		exit;		
       
  1181 		}
       
  1182 
       
  1183 	if ($platform eq "Winscw")
       
  1184 		{
       
  1185 		$kfPlatforms[1] = "All Winscw";
       
  1186 		}
       
  1187 	elsif (($platform eq "H6") || ($platform eq "H4 WDP") || ($platform eq "NaviEngine"))
       
  1188 		{
       
  1189 		$kfPlatforms[1] = "All HW";
       
  1190 		}
       
  1191 	else
       
  1192 		{
       
  1193 		print "\nERROR: The platform specified was not recognised, supported options: Winscw, H6, H4 WDP, NaviEngine.\n";
       
  1194 		exit;		
       
  1195 		}
       
  1196 	
       
  1197 	$kfPlatforms[2] = "$codeline $platform";
       
  1198 	}
       
  1199 
       
  1200 if ($iVerbose)
       
  1201 	{
       
  1202 	print "\nLog files found:\n";
       
  1203 	foreach my $file (@runResults)
       
  1204 		{
       
  1205 		my $scriptName = $file->ScriptName();
       
  1206 		print "$scriptName\n";
       
  1207 		}
       
  1208 	}
       
  1209 	
       
  1210 AnalyseFailures($aParams{k}, $aParams{r}, $aParams{i}, \@runResults, \@kfPlatforms);
       
  1211 
       
  1212 print "\n\nKnown failures:\n";
       
  1213 print "------------------\n";
       
  1214 print "$iKnownFails\n\n";
       
  1215 
       
  1216 print "Unknown failures but found in the reference build:\n";
       
  1217 print "----------------------------------------------------\n";
       
  1218 print "$iUnknownFailsButKnownInRef\n\n";
       
  1219 
       
  1220 print "Unknown failures but known in other codelines:\n";
       
  1221 print "------------------------------------------------\n";
       
  1222 print "$iUnknownFailsButKnownInOtherCodelines\n\n";
       
  1223 
       
  1224 print "Unknown failures:\n";
       
  1225 print "-------------------\n";
       
  1226 print "$iUnknownFails\n\n";
       
  1227 
       
  1228 print "Tests with reduced test counts:\n";
       
  1229 print "---------------------------------\n";
       
  1230 print "$iMissingTests\n\n";
       
  1231 
       
  1232