tsrc/qvptestresultgen.pl
changeset 61 3cd404d31176
equal deleted inserted replaced
58:ed94e1e8390e 61:3cd404d31176
       
     1 #
       
     2 # Copyright (c) 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 # 
       
    16 
       
    17 #------------------------------------------------------------------------------------
       
    18 # Includes
       
    19 #------------------------------------------------------------------------------------
       
    20 use strict;
       
    21 use warnings;
       
    22 use Cwd; # for cwd
       
    23 use FindBin; # for FindBin:Bin
       
    24 use File::Path; # for mkpath
       
    25 use Date::Calc;
       
    26 
       
    27 { # No globals.
       
    28     my $cgidir = GetCgiDir();
       
    29     #require( $cgidir . "utils.pl" );
       
    30 }
       
    31 
       
    32 #------------------------------------------------------------------------------------
       
    33 # Globals
       
    34 #------------------------------------------------------------------------------------
       
    35 my $lineFeed = "\n";
       
    36 
       
    37 my $RESULT_TESTCLASS =          0;      # string
       
    38 my $RESULT_TESTCASE =           1;      # string
       
    39 my $RESULT_PASSEDCOUNT =        2;      # num
       
    40 my $RESULT_FAILEDCOUNT =        3;      # num
       
    41 my $RESULT_SKIPPEDCOUNT =       4;      # num
       
    42 my $RESULT_TOTALCOUNT =         5;      # num
       
    43 my $RESULT_WARNINGMSGS =        6;      # array of strings
       
    44 my $RESULT_DEBUGMSGS =          7;      # array of strings
       
    45 my $RESULT_DEPRECATIONMSGS =    8;      # array of strings
       
    46 my $RESULT_ALLCASES =           9;     # array of arrays ( result(fail=0, pass=1), string method name, array of info strings )
       
    47     my $CASE_RESULT = 0;
       
    48     my $CASE_NAME = 1;
       
    49     my $CASE_INFO = 2;
       
    50 my $RESULT_SKIPPEDCASES =       10;     # array of strings
       
    51 
       
    52 my $optionTextReport = 0;
       
    53 
       
    54 #------------------------------------------------------------------------------------
       
    55 # Main code
       
    56 #------------------------------------------------------------------------------------
       
    57 
       
    58 ReadArgs();
       
    59 
       
    60 Main();
       
    61 
       
    62 exit();
       
    63 
       
    64 #------------------------------------------------------------------------------------
       
    65 # Subs
       
    66 #------------------------------------------------------------------------------------
       
    67 
       
    68 sub ReadArgs
       
    69 {
       
    70     while( scalar(@ARGV) > 0 )
       
    71     {
       
    72     	my $argument = shift(@ARGV);
       
    73     	
       
    74     	if( $argument eq "-h" )
       
    75     	{
       
    76     		ShowHelp();
       
    77     	}
       
    78     	elsif( $argument eq "-txt" )
       
    79     	{
       
    80             $optionTextReport = 1;
       
    81     	}
       
    82     	elsif( $argument ne "" )
       
    83     	{
       
    84     		print "Uknown argument: $argument\n";
       
    85     		ShowHelp();
       
    86     	}
       
    87     };
       
    88 }
       
    89 
       
    90 sub ShowHelp 
       
    91 {
       
    92 
       
    93 print <<USAGE_EOF;
       
    94 qvptestresultgen.pl <options: -h -txt>
       
    95   
       
    96 Options
       
    97   -h                    Shows help.
       
    98   -txt                  Creates test report in text format instead of xml (Excel).
       
    99 
       
   100 Copy the Qt test result files from device c:\\data to same folder with 
       
   101 the script and run it. Creates report from the results.
       
   102 
       
   103 Script can be run from videoplayer/internal/qt folder.
       
   104 
       
   105 USAGE_EOF
       
   106 
       
   107 	exit();
       
   108 
       
   109 }
       
   110 
       
   111 sub Main
       
   112 {
       
   113     my @files;
       
   114     FindFiles(".", "txt", 1, \@files);
       
   115 
       
   116     my @allResults;
       
   117 
       
   118     foreach my $file ( @files )
       
   119     {
       
   120         my @results;
       
   121 
       
   122         if( ReadTestRunResults( $file, \@results ) )
       
   123         {
       
   124             push @allResults, [ @results ];
       
   125         }
       
   126     }
       
   127     
       
   128     my @totals;
       
   129     GetTotals( \@totals, \@allResults );
       
   130     
       
   131     if( $optionTextReport )
       
   132     {
       
   133         CreateTextReport( \@totals, \@allResults );
       
   134     }
       
   135     else
       
   136     {
       
   137         CreateXmlReport( \@totals, \@allResults );
       
   138     }
       
   139 }
       
   140 
       
   141 sub ReadTestRunResults
       
   142 {
       
   143     my ( $file, $refResults ) = @_;
       
   144     
       
   145     open( FILE_HANDLE, $file ) or die("ERROR! Could not open file '" . $file . "'\n");
       
   146 	my @lines = <FILE_HANDLE>;
       
   147 	close(FILE_HANDLE);
       
   148 	
       
   149     my $isQtResultFile = 0;
       
   150     for( my $i = 0; $i < 10; $i++ )
       
   151     {
       
   152         if( $i < scalar( @lines ) && $lines[$i] =~ m/Using QTest library/i )
       
   153         {
       
   154             $isQtResultFile = 1;
       
   155             last;
       
   156         }
       
   157     }
       
   158     return 0 if( !$isQtResultFile );    
       
   159 	
       
   160 	@$refResults[$RESULT_TESTCLASS] = "";
       
   161 	@$refResults[$RESULT_TESTCASE] = "";
       
   162     @$refResults[$RESULT_PASSEDCOUNT] = 0;
       
   163     @$refResults[$RESULT_FAILEDCOUNT] = 0;
       
   164     @$refResults[$RESULT_SKIPPEDCOUNT] = 0;
       
   165     @$refResults[$RESULT_TOTALCOUNT] = 0;
       
   166     @$refResults[$RESULT_WARNINGMSGS] = [ () ];
       
   167     @$refResults[$RESULT_DEBUGMSGS] = [ () ];
       
   168     @$refResults[$RESULT_DEPRECATIONMSGS] = [ () ];
       
   169     @$refResults[$RESULT_ALLCASES] = [ () ];
       
   170     @$refResults[$RESULT_SKIPPEDCASES] = [ () ];
       
   171 	
       
   172 	for( my $i = 0; $i < scalar(@lines); $i++ )
       
   173 	{
       
   174 	    my $line = $lines[$i];
       
   175 	    
       
   176 	    #              msg                 class              function
       
   177 	    if( $line =~ /([a-z\!]+)[ ]+\:[ ]+([a-z0-9\_\-]+)\:\:([a-z0-9\_\-]+\(\))/i )
       
   178 	    {
       
   179 	        my $result = $1;
       
   180 	        my $testClass = $2;
       
   181 	        my $testFunc = $3;
       
   182 	        #print("result: $result, class: $testClass, func: $testFunc\n");
       
   183 	        
       
   184 	        @$refResults[$RESULT_TESTCLASS] = $testClass;
       
   185 	        @$refResults[$RESULT_TESTCASE] = $testFunc;
       
   186 	        
       
   187 	        my @case;
       
   188 	        $case[$CASE_RESULT] = -1;
       
   189 	        $case[$CASE_NAME] = $testClass . "::" . $testFunc;;
       
   190 	        $case[$CASE_INFO] = [ () ];
       
   191 	        
       
   192 	        if( $result =~ /pass/i )
       
   193 	        {
       
   194 	            @$refResults[$RESULT_PASSEDCOUNT]++;
       
   195 	            $case[$CASE_RESULT] = 1;
       
   196 	        }
       
   197 	        if( $result =~ /fail\!/i )
       
   198 	        {
       
   199 	            @$refResults[$RESULT_FAILEDCOUNT]++;
       
   200 	            
       
   201                 $case[$CASE_RESULT] = 0;
       
   202                 
       
   203 	            my @info;
       
   204 	            # Read rest of the line for info.
       
   205 	            my $reason = substr( $line, rindex( $line, $testFunc ) + length( $testFunc ) );
       
   206 	            RemoveWhiteSpaces( \$reason );
       
   207 	            push @info, $reason;
       
   208 
       
   209                 # Read next lines starting with space to info.
       
   210                 while( $lines[$i+1] =~ m/^ / )
       
   211                 {
       
   212                     my $str = $lines[$i+1];
       
   213                     RemoveWhiteSpaces( \$str );
       
   214                     push @info, $str;
       
   215                     $i++;                    
       
   216                     last if(!defined($lines[$i+1]));
       
   217                 }
       
   218 
       
   219 	            $case[$CASE_INFO] = [ @info ];
       
   220 	        }
       
   221 	        
       
   222 	        my $refAllCases = @$refResults[$RESULT_ALLCASES];
       
   223 	        push @$refAllCases, [ @case ];
       
   224 	        
       
   225 	        if( $result =~ /skip/i )
       
   226 	        {
       
   227 	            @$refResults[$RESULT_SKIPPEDCOUNT]++;
       
   228 	            push @{@$refResults[$RESULT_SKIPPEDCASES]}, $testClass . "::" . $testFunc;
       
   229 	        }
       
   230 	        if( $result =~ /qdebug/i )
       
   231 	        {
       
   232 	            push @{@$refResults[$RESULT_DEBUGMSGS]}, $line;
       
   233 	            if( $line =~ m/deprecated/i )
       
   234 	            {
       
   235     	            push @{@$refResults[$RESULT_DEPRECATIONMSGS]}, $line;
       
   236 	            }
       
   237 	        }
       
   238 	        if( $result =~ /qwarn/i )
       
   239 	        {
       
   240 	            push @{@$refResults[$RESULT_WARNINGMSGS]}, $line;
       
   241 	        }	        
       
   242 	    }
       
   243 	}
       
   244 	
       
   245 	@$refResults[$RESULT_TOTALCOUNT] = @$refResults[$RESULT_PASSEDCOUNT] + @$refResults[$RESULT_FAILEDCOUNT] + @$refResults[$RESULT_SKIPPEDCOUNT];
       
   246 	return 1;
       
   247 }
       
   248 
       
   249 sub GetTotals
       
   250 {
       
   251     my ( $refTotals, $refAllResults ) = @_;
       
   252 	
       
   253 	@$refTotals[$RESULT_TESTCLASS] = "";
       
   254 	@$refTotals[$RESULT_TESTCASE] = "";
       
   255     @$refTotals[$RESULT_PASSEDCOUNT] = 0;
       
   256     @$refTotals[$RESULT_FAILEDCOUNT] = 0;
       
   257     @$refTotals[$RESULT_SKIPPEDCOUNT] = 0;
       
   258     @$refTotals[$RESULT_TOTALCOUNT] = 0;
       
   259     @$refTotals[$RESULT_WARNINGMSGS] = [ () ];
       
   260     @$refTotals[$RESULT_DEBUGMSGS] = [ () ];
       
   261     @$refTotals[$RESULT_DEPRECATIONMSGS] = [ () ];
       
   262     @$refTotals[$RESULT_ALLCASES] = [ () ];
       
   263     @$refTotals[$RESULT_SKIPPEDCASES] = [ () ];
       
   264     
       
   265     foreach my $refResults ( @$refAllResults )
       
   266     {   
       
   267     	@$refTotals[$RESULT_TESTCLASS] = "";
       
   268     	@$refTotals[$RESULT_TESTCASE] = "";
       
   269         @$refTotals[$RESULT_PASSEDCOUNT] += @$refResults[$RESULT_PASSEDCOUNT];
       
   270         @$refTotals[$RESULT_FAILEDCOUNT] += @$refResults[$RESULT_FAILEDCOUNT];
       
   271         @$refTotals[$RESULT_SKIPPEDCOUNT] += @$refResults[$RESULT_SKIPPEDCOUNT];
       
   272         @$refTotals[$RESULT_TOTALCOUNT] += @$refResults[$RESULT_TOTALCOUNT];
       
   273         @$refTotals[$RESULT_WARNINGMSGS] = [ ( @{@$refTotals[$RESULT_WARNINGMSGS]}, @{@$refResults[$RESULT_WARNINGMSGS]} ) ];
       
   274         @$refTotals[$RESULT_DEBUGMSGS] = [ ( @{@$refTotals[$RESULT_DEBUGMSGS]}, @{@$refResults[$RESULT_DEBUGMSGS]} ) ];
       
   275         @$refTotals[$RESULT_DEPRECATIONMSGS] = [ ( @{@$refTotals[$RESULT_DEPRECATIONMSGS]}, @{@$refResults[$RESULT_DEPRECATIONMSGS]} ) ];
       
   276         @$refTotals[$RESULT_ALLCASES] = [ ( @{@$refTotals[$RESULT_ALLCASES]}, @{@$refResults[$RESULT_ALLCASES]} ) ];
       
   277         @$refTotals[$RESULT_SKIPPEDCASES] = [ ( @{@$refTotals[$RESULT_SKIPPEDCASES]}, @{@$refResults[$RESULT_SKIPPEDCASES]} ) ];
       
   278     }
       
   279 }
       
   280 
       
   281 
       
   282 sub CreateTextReport
       
   283 {
       
   284     my ( $refTotals, $refAllResults ) = @_;
       
   285 
       
   286     my $template = 
       
   287 "
       
   288 Test Results for qvideoplayer
       
   289 
       
   290 HW:
       
   291 SW:
       
   292 
       
   293 Test Execution Metrics
       
   294 Passed: TEMPLATE_PASSED
       
   295 Failed: TEMPLATE_FAILED
       
   296 N/A (skipped): TEMPLATE_SKIPPED
       
   297 Total number of cases: TEMPLATE_TOTAL
       
   298 Pass rate of total: TEMPLATE_PRT
       
   299 Pass rate of planned: TEMPLATE_PRP
       
   300 
       
   301 Tests
       
   302 TEMPLATE_TESTLIST
       
   303 
       
   304 Warnings: 
       
   305 TEMPLATE_WARNINGS
       
   306 Debug message count from tests: TEMPLATE_DEBUG_COUNT
       
   307 Deprecation message count from tests: TEMPLATE_DEPRECATION_COUNT
       
   308 
       
   309 Failed test cases:
       
   310 TEMPLATE_FAILED_CASES
       
   311 
       
   312 Passed test cases
       
   313 TEMPLATE_PASSED_CASES
       
   314 
       
   315 ";
       
   316     
       
   317     # List of tests.
       
   318 
       
   319     my $str = "";
       
   320     
       
   321     my @testResults;
       
   322     GetTestResults(\@testResults, $refAllResults);
       
   323     foreach my $refRes( @testResults )
       
   324     {
       
   325         my $testName =  @$refRes[0];
       
   326         my $testResult =  @$refRes[1];
       
   327         RemoveWhiteSpaces( \$testName );
       
   328         RemoveWhiteSpaces( \$testResult );
       
   329         $str .= " $testName $testResult\n" if( $testName ne "" );        
       
   330     }
       
   331     
       
   332     $template =~ s/TEMPLATE_TESTLIST/$str/;
       
   333 
       
   334     # Numeric data.
       
   335     
       
   336     $template =~ s/TEMPLATE_PASSED/@$refTotals[$RESULT_PASSEDCOUNT]/;
       
   337     $template =~ s/TEMPLATE_FAILED/@$refTotals[$RESULT_FAILEDCOUNT]/;
       
   338     $template =~ s/TEMPLATE_SKIPPED/@$refTotals[$RESULT_SKIPPEDCOUNT]/;
       
   339     $template =~ s/TEMPLATE_TOTAL/@$refTotals[$RESULT_TOTALCOUNT]/;
       
   340     
       
   341     # Pass rates.
       
   342     
       
   343     my $prt = @$refTotals[$RESULT_PASSEDCOUNT] / @$refTotals[$RESULT_TOTALCOUNT] * 100;
       
   344     $prt = sprintf( "%.2f", $prt );
       
   345     $template =~ s/TEMPLATE_PRT/$prt/;
       
   346     
       
   347     my $prp =  @$refTotals[$RESULT_PASSEDCOUNT] / ( @$refTotals[$RESULT_PASSEDCOUNT] + @$refTotals[$RESULT_FAILEDCOUNT] ) * 100;
       
   348     $prp = sprintf( "%.2f", $prp );
       
   349     $template =~ s/TEMPLATE_PRP/$prp/;
       
   350     
       
   351     # Message counts.
       
   352     
       
   353     $str = "";
       
   354     foreach my $warning ( @{@$refTotals[$RESULT_WARNINGMSGS]} )
       
   355     {
       
   356         RemoveWhiteSpaces( \$warning );
       
   357         $str .= " $warning\n";
       
   358     }
       
   359     $template =~ s/TEMPLATE_WARNINGS/$str/;
       
   360     
       
   361     my $count = scalar( @{@$refTotals[$RESULT_DEBUGMSGS]} );
       
   362     $template =~ s/TEMPLATE_DEBUG_COUNT/$count/;
       
   363     
       
   364     $count = scalar( @{@$refTotals[$RESULT_DEPRECATIONMSGS]} );
       
   365     $template =~ s/TEMPLATE_DEPRECATION_COUNT/$count/;
       
   366 
       
   367     # Failed cases.
       
   368 
       
   369     $str = "\n";
       
   370     foreach my $refCase ( @{@$refTotals[$RESULT_ALLCASES]} )
       
   371     {
       
   372         if( @$refCase[$CASE_RESULT] == 0 )
       
   373         {
       
   374             my $case = @$refCase[$CASE_NAME];
       
   375             my $refInfoArray = @$refCase[$CASE_INFO];
       
   376             if( $case ne "" )
       
   377             {
       
   378                 $str .= " $case \n";
       
   379                 $str .= "    Info: \n";
       
   380                 foreach my $infoLine ( @$refInfoArray )
       
   381                 {                
       
   382                     $str .= "     $infoLine \n";
       
   383                 }
       
   384             }
       
   385             $str .= "\n";
       
   386         }
       
   387     }
       
   388     $str = substr( $str, 0, length( $str ) - 1 ) if( length( $str ) > 1 ); # Remove line break from last line.
       
   389     $template =~ s/TEMPLATE_FAILED_CASES/$str/;
       
   390 
       
   391     # Passed cases.
       
   392 
       
   393     $str = "\n";
       
   394     foreach my $refCase ( @{@$refTotals[$RESULT_ALLCASES]} )
       
   395     {
       
   396         if( @$refCase[$CASE_RESULT] == 1) 
       
   397         {
       
   398             my $case = @$refCase[$CASE_NAME];
       
   399             $str .= " $case \n";
       
   400         }
       
   401     }
       
   402 
       
   403     $str = substr( $str, 0, length( $str ) - 1 ) if( length( $str ) > 1 ); # Remove line break from last line.
       
   404     $template =~ s/TEMPLATE_PASSED_CASES/$str/;
       
   405     
       
   406     # Print to default output and file.
       
   407     print( $template);
       
   408     
       
   409 	open(FILE_HANDLE, ">" . "qvptestreport.txt") or die("ERROR! Could not open file '" . "qvptestreport.txt" . "'\n");
       
   410     print FILE_HANDLE $template;
       
   411     close FILE_HANDLE;
       
   412 }
       
   413 
       
   414 sub CreateXmlReport
       
   415 {
       
   416     my ( $refTotals, $refAllResults ) = @_;
       
   417 
       
   418     my $data = "";
       
   419     my $str = "";
       
   420     
       
   421     my $rows = @$refTotals[$RESULT_TOTALCOUNT] + scalar( @{@$refTotals[$RESULT_WARNINGMSGS]} ) + scalar( @{@$refTotals[$RESULT_DEBUGMSGS]} ) +
       
   422                scalar( @{@$refTotals[$RESULT_DEPRECATIONMSGS]} );
       
   423     
       
   424     # Excel xml header
       
   425     
       
   426     $data = XmlHeader( $rows*2 + 100 );
       
   427     
       
   428     $data .= XmlEmptyRow();
       
   429 
       
   430     # HW and SW
       
   431 
       
   432     $str = XmlSwHwRow();
       
   433     $str =~ s/REPLACE/INSERT SW HERE/;
       
   434     $data .= $str;
       
   435     
       
   436     $str = XmlSwHwRow();
       
   437     $str =~ s/REPLACE/INSERT HW HERE/;
       
   438     $data .= $str;
       
   439                 
       
   440     $data .= XmlEmptyRow();
       
   441     
       
   442     # Metrics
       
   443 
       
   444     my $passCount = @$refTotals[$RESULT_PASSEDCOUNT];
       
   445     my $failCount = @$refTotals[$RESULT_FAILEDCOUNT];
       
   446     my $skipCount = @$refTotals[$RESULT_SKIPPEDCOUNT];
       
   447     my $totalCount = @$refTotals[$RESULT_TOTALCOUNT];
       
   448         
       
   449     my $passRateTotal = $passCount / $totalCount * 100;
       
   450     $passRateTotal = sprintf( "%.2f", $passRateTotal );
       
   451     
       
   452     my $passRateRun =  $passCount / ( $passCount + $failCount ) * 100;
       
   453     $passRateRun = sprintf( "%.2f", $passRateRun );
       
   454     
       
   455     my $runRate = ( $passCount + $failCount ) / $totalCount * 100;
       
   456     $runRate = sprintf( "%.2f", $runRate );
       
   457     
       
   458     $str = XmlMetrics();
       
   459     $str =~ s/TOTALCASECOUNT/$totalCount/;
       
   460     $str =~ s/PASSEDCASECOUNT/$passCount/;
       
   461     $str =~ s/FAILEDCASECOUNT/$failCount/;
       
   462     $str =~ s/SKIPPEDCASECOUNT/$skipCount/;
       
   463     $str =~ s/PASSRATEOFTOTAL/$passRateTotal/;
       
   464     $str =~ s/PASSRATEOFRUN/$passRateRun/;
       
   465     $str =~ s/RUNRATE/$runRate/;
       
   466     $data .= $str;
       
   467 
       
   468     $data .= XmlEmptyRow();
       
   469         
       
   470     # List of tests.
       
   471 
       
   472     $str = XmlTitleOnBlueRow();
       
   473     $str =~ s/THETITLE/Tests/;
       
   474     $data .= $str;
       
   475 
       
   476     my @testResults;
       
   477     GetTestResults(\@testResults, $refAllResults);
       
   478     foreach my $refRes( @testResults )
       
   479     {
       
   480         $str = XmlTestNameRow();
       
   481         my $testName =  @$refRes[0];
       
   482         my $testResult =  @$refRes[1];
       
   483         XmlReadyText( \$testName );
       
   484         XmlReadyText( \$testResult );
       
   485         RemoveWhiteSpaces( \$testName );
       
   486         RemoveWhiteSpaces( \$testResult );
       
   487         $str =~ s/TESTNAME/$testName/;
       
   488         $str =~ s/TESTRESULT/$testResult/;
       
   489         $data .= $str;
       
   490     }
       
   491     
       
   492     $data .= XmlEmptyRow();
       
   493     
       
   494     # Case list.
       
   495 
       
   496     $str = XmlTitleOnBlueRow();
       
   497     $str =~ s/THETITLE/Cases/;
       
   498     $data .= $str;
       
   499 
       
   500     my $cleanupTestCaseFound = 0;
       
   501     my $caseName = "";
       
   502     my $caseTestClass = "";
       
   503 
       
   504     foreach my $refCase ( @{@$refTotals[$RESULT_ALLCASES]} )
       
   505     {
       
   506         $caseName = @$refCase[$CASE_NAME];
       
   507         
       
   508         # Write warning if cleanupTestCase is not found for the test.
       
   509         if( index($caseName, "::") != -1 )
       
   510         {
       
   511             my $tc = substr($caseName, 0, index($caseName, "::"));
       
   512             if($caseTestClass ne "" && $caseTestClass ne $tc)
       
   513             {
       
   514                 if(!$cleanupTestCaseFound) 
       
   515                 {
       
   516                     $str = XmlTextRowRed();
       
   517                     $str =~ s/REPLACE/cleanupTestCase was not found! Test did not finish?/;
       
   518                     $data .= $str;            
       
   519                 }
       
   520                 $cleanupTestCaseFound = 0;
       
   521             }
       
   522             $caseTestClass = $tc;
       
   523         }
       
   524         $cleanupTestCaseFound = 1 if($caseName =~ "cleanupTestCase");
       
   525         
       
   526         next if( $caseName eq "" );
       
   527 
       
   528         if( @$refCase[$CASE_RESULT] == 0 )
       
   529         {
       
   530             my $infoStr = "";
       
   531             my $refInfoArray = @$refCase[$CASE_INFO];
       
   532             foreach my $infoLine ( @$refInfoArray )
       
   533             {                
       
   534                 $infoStr .= "$infoLine\n";
       
   535             }
       
   536             
       
   537             $str = XmlFailedCaseRow();
       
   538             XmlReadyText( \$caseName );
       
   539             $str =~ s/TESTCASENAME/$caseName/;            
       
   540             XmlReadyText( \$infoStr );
       
   541             $str =~ s/FAILREASON/$infoStr/;
       
   542             $data .= $str;
       
   543         }
       
   544         elsif( @$refCase[$CASE_RESULT] == 1 )
       
   545         {
       
   546             $str = XmlPassedCaseRow();
       
   547             XmlReadyText( \$caseName );
       
   548             $str =~ s/TESTCASENAME/$caseName/;            
       
   549             $data .= $str;
       
   550         }
       
   551     }    
       
   552     
       
   553     $data .= XmlEmptyRow();
       
   554   
       
   555     # Warning messages
       
   556     
       
   557     $str = XmlTitleOnBlueRow();
       
   558     $str =~ s/THETITLE/Warning messages/;
       
   559     $data .= $str;
       
   560     
       
   561     foreach my $warning ( @{@$refTotals[$RESULT_WARNINGMSGS]} )
       
   562     {
       
   563         RemoveWhiteSpaces( \$warning );
       
   564         XmlReadyText( \$warning );
       
   565         $str = XmlMessageRow();        
       
   566         $str =~ s/MESSAGE/$warning/;
       
   567         $data .= $str;        
       
   568     }
       
   569     
       
   570     $data .= XmlEmptyRow();
       
   571     
       
   572     # Message counts.
       
   573 
       
   574     my $msgCountStr = "Debug message count: " . scalar( @{@$refTotals[$RESULT_DEBUGMSGS]} );
       
   575     $str = XmlMessageRow();
       
   576     $str =~ s/MESSAGE/$msgCountStr/;
       
   577     $data .= $str;
       
   578 
       
   579     $msgCountStr = "Deprecation message count: " . scalar( @{@$refTotals[$RESULT_DEPRECATIONMSGS]} );
       
   580     $str = XmlMessageRow();
       
   581     $str =~ s/MESSAGE/$msgCountStr/;
       
   582     $data .= $str;
       
   583     
       
   584     for( my $i = 0; $i < 20; $i++ ) 
       
   585     {
       
   586         $data .= XmlEmptyRow();
       
   587     }
       
   588     
       
   589     # Excel xml footer.
       
   590     $data .= XmlFooter();
       
   591 
       
   592     open(FILE_HANDLE, ">" . "qvptestreport.xml") or die("ERROR! Could not open file '" . "qvptestreport.xml" . "'\n");
       
   593     print FILE_HANDLE $data;
       
   594     close FILE_HANDLE;
       
   595 }
       
   596 
       
   597 sub GetTestResults
       
   598 {
       
   599     my ($refResults, $refAllResults) = @_;
       
   600 
       
   601     # Read tests and results from file.
       
   602     open(TRFH, "qvptestresults.txt") or return "";
       
   603     my @lines = <TRFH>;
       
   604     close(TRFH);
       
   605     
       
   606     foreach my $line( @lines )
       
   607     {
       
   608         my @res = split(/\t/, $line);
       
   609         RemoveWhiteSpaces(\$res[0]);
       
   610         RemoveWhiteSpaces(\$res[1]);
       
   611         
       
   612         # Check if there's already result for the test.
       
   613         my $found = 0;
       
   614         foreach my $refRes ( @$refResults ) 
       
   615         {
       
   616             if(@$refRes[0] eq $res[0] )
       
   617             {
       
   618                 # Update test result.
       
   619                 @$refRes[1] .= " " . $res[1];
       
   620                 $found = 1;
       
   621                 last;
       
   622             }
       
   623         }
       
   624         
       
   625         # Test not found, add new.
       
   626         if( !$found )
       
   627         {
       
   628             push @$refResults, [ @res ];
       
   629         }
       
   630     }
       
   631 
       
   632     # And add those tests that were not in the result file.
       
   633 
       
   634     foreach my $refResult ( @$refAllResults )
       
   635     {
       
   636         my $testName = @$refResult[$RESULT_TESTCLASS];
       
   637 
       
   638         my $found = 0;
       
   639         foreach my $refRes ( @$refResults ) 
       
   640         {
       
   641             if(@$refRes[0] eq $testName )
       
   642             {
       
   643                 $found = 1;
       
   644                 last;
       
   645             }
       
   646         }
       
   647         
       
   648         if(!$found)
       
   649         {
       
   650             push @$refResults, [ ($testName, "" ) ];
       
   651         }
       
   652     }        
       
   653 }
       
   654 
       
   655 sub FindFiles
       
   656 {
       
   657 	my ($godir, $fileSearch, $searchType, $refIncfiles) = @_;
       
   658 
       
   659 	my $startDir = cwd;
       
   660 
       
   661 	chdir($godir) or return;
       
   662 
       
   663 	#print("Now in: " . cwd . "\n");
       
   664 
       
   665 	opendir(DIR, ".");
       
   666 	my @filelist = sort(readdir(DIR));
       
   667 	closedir(DIR);
       
   668 
       
   669 	foreach my $file(@filelist)
       
   670 	{
       
   671 		if($file eq "." or $file eq "..") {next};
       
   672 
       
   673 		if (-d $file)
       
   674 		{
       
   675 		 	FindFiles( $file, $fileSearch, $searchType, $refIncfiles);
       
   676 		} else
       
   677 		{
       
   678 			if( ($file =~ m/$fileSearch/i and $searchType == 0 ) or ($file =~ m/$fileSearch$/i and $searchType == 1 ) )
       
   679 			{
       
   680                 $file = cwd . "/" . $file;
       
   681 				push @$refIncfiles, $file;
       
   682 				#print("$file\n");
       
   683 			}
       
   684 		}
       
   685 	}
       
   686 
       
   687 	chdir ($startDir);
       
   688 }
       
   689 
       
   690 
       
   691 sub GetCgiDir
       
   692   {
       
   693     # Solve where the script is located.
       
   694     $0=~/^(.+[\\\/])[^\\\/]+[\\\/]*$/;
       
   695     my $cgidir= $1 || "./";
       
   696     
       
   697     # And try to solve relative path.
       
   698     if( index( $cgidir, "..\\" ) != -1 )
       
   699     {
       
   700     	my $p = cwd;
       
   701     	$p =~ s/\//\\/g;
       
   702     	$cgidir =~ s/\//\\/g;
       
   703     	while(1) 
       
   704     	{
       
   705     		my $pos = index( $cgidir, "..\\" );
       
   706     		last if( $pos == -1 );
       
   707     		$cgidir = substr( $cgidir, $pos+3 );
       
   708     		
       
   709     		$pos = rindex( $p, "\\" );
       
   710     		last if( $pos == -1 );
       
   711     		$p = substr( $p, 0, $pos);
       
   712     	}
       
   713     	$cgidir = $p . "\\" . $cgidir;
       
   714     }
       
   715     return $cgidir;
       
   716 }
       
   717 
       
   718 sub GetPathFileName
       
   719 {
       
   720     my ($str) = @_;
       
   721 
       
   722     my $startPos = rindex($str, "\\");
       
   723     if($startPos == -1)
       
   724     {
       
   725         $startPos = rindex($str, "/");
       
   726         return $str if($startPos == -1);
       
   727     }
       
   728 
       
   729     my $filename = substr($str, $startPos+1);
       
   730 
       
   731     return $filename;
       
   732 }
       
   733 
       
   734 sub GetPathDir
       
   735 {
       
   736     my ($str) = @_;
       
   737 
       
   738     my $endPos = rindex($str, "\\");
       
   739     if($endPos == -1)
       
   740     {
       
   741         $endPos = rindex($str, "/");
       
   742         return $str if($endPos == -1);
       
   743     }
       
   744 
       
   745     my $filename = substr($str, 0, $endPos);
       
   746 
       
   747     return $filename;
       
   748 }
       
   749 
       
   750 sub RemoveWhiteSpaces
       
   751 {
       
   752 	my ($text) = @_;
       
   753 	${$text} =~ s/\s+$//; #whitespaces in the end
       
   754 	${$text} =~ s/^\s+//; #whitespaces at the start
       
   755 }
       
   756 
       
   757 sub XmlReadyText
       
   758 {
       
   759 	my ($text) = @_;
       
   760 
       
   761 	my $txtlt = "&lt;";
       
   762 	my $txtgt = "&gt;";
       
   763 	${$text} =~ s/</$txtlt/g;
       
   764 	${$text} =~ s/>/$txtgt/g;
       
   765 
       
   766 	${$text} =~ s/Ä/&Auml/g;
       
   767 	${$text} =~ s/ä/&auml/g;
       
   768 	${$text} =~ s/Ö/&Ouml/g;
       
   769 	${$text} =~ s/ö/&ouml/g;
       
   770 
       
   771 	#ä &auml;
       
   772 
       
   773 #	Ö &Ouml;
       
   774 
       
   775 #	ö &ouml;
       
   776 }
       
   777 
       
   778 sub XmlHeader 
       
   779 { 
       
   780     my ( $rowCount ) = @_;
       
   781     my $str =
       
   782 "<?xml version=\"1.0\"?>\n" .
       
   783 "<?mso-application progid=\"Excel.Sheet\"?>\n" .
       
   784 "<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\n" .
       
   785 " xmlns:o=\"urn:schemas-microsoft-com:office:office\"\n" .
       
   786 " xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\n" .
       
   787 " xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"\n" .
       
   788 " xmlns:html=\"http://www.w3.org/TR/REC-html40\">\n" .
       
   789 " <DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\n" .
       
   790 "  <Author>Senbom Petri</Author>\n" .
       
   791 "  <LastAuthor>Senbom Petri</LastAuthor>\n" .
       
   792 "  <Created>2006-06-09T11:08:05Z</Created>\n" .
       
   793 "  <Company>Nokia Oyj</Company>\n" .
       
   794 "  <Version>11.9999</Version>\n" .
       
   795 " </DocumentProperties>\n" .
       
   796 " <ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">\n" .
       
   797 "  <WindowHeight>12210</WindowHeight>\n" .
       
   798 "  <WindowWidth>18780</WindowWidth>\n" .
       
   799 "  <WindowTopX>360</WindowTopX>\n" .
       
   800 "  <WindowTopY>255</WindowTopY>\n" .
       
   801 "  <ProtectStructure>False</ProtectStructure>\n" .
       
   802 "  <ProtectWindows>False</ProtectWindows>\n" .
       
   803 " </ExcelWorkbook>\n" .
       
   804 " <Styles>\n" .
       
   805 "  <Style ss:ID=\"Default\" ss:Name=\"Normal\">\n" .
       
   806 "   <Alignment ss:Vertical=\"Bottom\"/>\n" .
       
   807 "   <Borders/>\n" .
       
   808 "   <Font/>\n" .
       
   809 "   <Interior/>\n" .
       
   810 "   <NumberFormat/>\n" .
       
   811 "   <Protection/>\n" .
       
   812 "  </Style>\n" .
       
   813 "  <Style ss:ID=\"m153896384\">\n" .
       
   814 "   <Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Bottom\"/>\n" .
       
   815 "   <Borders>\n" .
       
   816 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   817 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   818 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   819 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   820 "   </Borders>\n" .
       
   821 "   <Font x:Family=\"Swiss\"/>\n" .
       
   822 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   823 "  </Style>\n" .
       
   824 "  <Style ss:ID=\"m153896394\">\n" .
       
   825 "   <Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Top\" ss:WrapText=\"1\"/>\n" .
       
   826 "   <Borders>\n" .
       
   827 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   828 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   829 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   830 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   831 "   </Borders>\n" .
       
   832 "   <Font x:Family=\"Swiss\"/>\n" .
       
   833 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   834 "   <NumberFormat/>\n" .
       
   835 "  </Style>\n" .
       
   836 "  <Style ss:ID=\"m153895896\">\n" .
       
   837 "   <Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Center\"/>\n" .
       
   838 "   <Borders>\n" .
       
   839 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   840 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   841 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   842 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   843 "   </Borders>\n" .
       
   844 "   <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\n" .
       
   845 "   <Interior ss:Color=\"#FFFF00\" ss:Pattern=\"Solid\"/>\n" .
       
   846 "  </Style>\n" .
       
   847 "  <Style ss:ID=\"redbg\">\n" .
       
   848 "   <Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Center\"/>\n" .
       
   849 "   <Borders>\n" .
       
   850 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   851 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   852 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   853 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   854 "   </Borders>\n" .
       
   855 "   <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\n" .
       
   856 "   <Interior ss:Color=\"#FF0000\" ss:Pattern=\"Solid\"/>\n" .
       
   857 "  </Style>\n" .
       
   858 "  <Style ss:ID=\"m153895906\">\n" .
       
   859 "   <Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Center\"/>\n" .
       
   860 "   <Borders>\n" .
       
   861 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   862 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   863 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   864 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   865 "   </Borders>\n" .
       
   866 "   <Font x:Family=\"Swiss\"/>\n" .
       
   867 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   868 "  </Style>\n" .
       
   869 "  <Style ss:ID=\"m153881708\">\n" .
       
   870 "   <Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Bottom\"/>\n" .
       
   871 "   <Borders>\n" .
       
   872 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   873 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   874 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   875 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   876 "   </Borders>\n" .
       
   877 "   <Font x:Family=\"Swiss\"/>\n" .
       
   878 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   879 "  </Style>\n" .
       
   880 "  <Style ss:ID=\"m153881728\">\n" .
       
   881 "   <Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Bottom\"/>\n" .
       
   882 "   <Borders>\n" .
       
   883 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   884 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   885 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   886 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   887 "   </Borders>\n" .
       
   888 "   <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\n" .
       
   889 "   <Interior ss:Color=\"#99CCFF\" ss:Pattern=\"Solid\"/>\n" .
       
   890 "  </Style>\n" .
       
   891 "  <Style ss:ID=\"m153881376\">\n" .
       
   892 "   <Alignment ss:Horizontal=\"Right\" ss:Vertical=\"Bottom\"/>\n" .
       
   893 "   <Borders>\n" .
       
   894 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>" .
       
   895 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   896 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   897 "   </Borders>\n" .
       
   898 "   <Interior ss:Color=\"#99CCFF\" ss:Pattern=\"Solid\"/>\n" .
       
   899 "  </Style>\n" .
       
   900 "  <Style ss:ID=\"m153881436\">\n" .
       
   901 "   <Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Bottom\"/>\n" .
       
   902 "   <Borders>\n" .
       
   903 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   904 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   905 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   906 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   907 "   </Borders>\n" .
       
   908 "   <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\n" .
       
   909 "   <Interior ss:Color=\"#99CCFF\" ss:Pattern=\"Solid\"/>\n" .
       
   910 "  </Style>\n" .
       
   911 "  <Style ss:ID=\"m153895744\">\n" .
       
   912 "   <Alignment ss:Horizontal=\"Right\" ss:Vertical=\"Bottom\"/>\n" .
       
   913 "   <Borders>\n" .
       
   914 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   915 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   916 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>" .
       
   917 "   </Borders>\n" .
       
   918 "   <Interior ss:Color=\"#99CCFF\" ss:Pattern=\"Solid\"/>\n" .
       
   919 "  </Style>\n" .
       
   920 "  <Style ss:ID=\"s24\">\n" .
       
   921 "   <Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Bottom\"/>\n" .
       
   922 "   <Borders>\n" .
       
   923 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   924 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   925 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>" .
       
   926 "   </Borders>\n" .
       
   927 "   <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\n" .
       
   928 "  </Style>\n" .
       
   929 "  <Style ss:ID=\"s27\">\n" .
       
   930 "   <Borders>\n" .
       
   931 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   932 "   </Borders>\n" .
       
   933 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   934 "  </Style>\n" .
       
   935 "  <Style ss:ID=\"s32\">\n" .
       
   936 "   <Alignment ss:Vertical=\"Top\" ss:WrapText=\"1\"/>\n" .
       
   937 "   <Borders>\n" .
       
   938 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   939 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   940 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   941 "   </Borders>\n" .
       
   942 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   943 "  </Style>\n" .
       
   944 "  <Style ss:ID=\"s34\">\n" .
       
   945 "   <Alignment ss:Horizontal=\"Right\" ss:Vertical=\"Bottom\"/>\n" .
       
   946 "   <Borders>\n" .
       
   947 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   948 "<Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>" .
       
   949 "   </Borders>\n" .
       
   950 "   <Interior ss:Color=\"#99CCFF\" ss:Pattern=\"Solid\"/>\n" .
       
   951 "  </Style>\n" .
       
   952 "  <Style ss:ID=\"s35\">\n" .
       
   953 "   <Alignment ss:Vertical=\"Top\" ss:WrapText=\"1\"/>\n" .
       
   954 "   <Borders>\n" .
       
   955 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   956 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   957 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   958 "   </Borders>\n" .
       
   959 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   960 "   <NumberFormat ss:Format=\"Fixed\"/>\n" .
       
   961 "  </Style>\n" .
       
   962 "  <Style ss:ID=\"s48\">\n" .
       
   963 "   <Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Bottom\"/>\n" .
       
   964 "   <Borders>\n" .
       
   965 "    <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   966 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   967 "    <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   968 "    <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   969 "   </Borders>\n" .
       
   970 "   <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\n" .
       
   971 "   <Interior ss:Color=\"#CCFFCC\" ss:Pattern=\"Solid\"/>\n" .
       
   972 "  </Style>\n" .
       
   973 "  <Style ss:ID=\"s109\">\n" .
       
   974 "   <Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Bottom\"/>\n" .
       
   975 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   976 "  </Style>\n" .
       
   977 "  <Style ss:ID=\"REDTEXT\">\n" .
       
   978 "   <Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Bottom\"/>\n" .
       
   979 "   <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\n" .
       
   980 "   <Interior ss:Color=\"#FF0000\" ss:Pattern=\"Solid\"/>\n" .
       
   981 "  </Style>\n" .
       
   982 "  <Style ss:ID=\"s111\">\n" .
       
   983 "   <Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Bottom\"/>\n" .
       
   984 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   985 "  </Style>\n" .
       
   986 "  <Style ss:ID=\"s119\">\n" .
       
   987 "   <Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Bottom\"/>\n" .
       
   988 "   <Borders>\n" .
       
   989 "    <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n" .
       
   990 "   </Borders>\n" .
       
   991 "   <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\n" .
       
   992 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   993 "  </Style>\n" .
       
   994 "  <Style ss:ID=\"s82\">\n" .
       
   995 "   <Interior ss:Color=\"#FFFFFF\" ss:Pattern=\"Solid\"/>\n" .
       
   996 "  </Style>\n" .
       
   997 " </Styles> \n" .
       
   998 " <Worksheet ss:Name=\"Sheet1\">\n" .
       
   999 "  <Table ss:ExpandedColumnCount=\"15\" ss:ExpandedRowCount=\"EXCELEXPANDEDROWCOUNT\" x:FullColumns=\"1\"\n" .
       
  1000 "   x:FullRows=\"1\">\n" .
       
  1001 "   <Column ss:StyleID=\"s82\" ss:AutoFitWidth=\"0\" ss:Width=\"12.75\"/>\n" .
       
  1002 "   <Column ss:AutoFitWidth=\"0\" ss:Width=\"63\"/>\n" .
       
  1003 "   <Column ss:AutoFitWidth=\"0\" ss:Width=\"69\"/>\n" .
       
  1004 "   <Column ss:AutoFitWidth=\"0\" ss:Width=\"78\"/>\n" .
       
  1005 "   <Column ss:AutoFitWidth=\"0\" ss:Width=\"197.25\"/>\n" .
       
  1006 "   <Column ss:AutoFitWidth=\"0\" ss:Width=\"388.5\"/>\n" .
       
  1007 "   <Column ss:AutoFitWidth=\"0\" ss:Width=\"39\" ss:Span=\"1\"/>\n" .
       
  1008 "   <Column ss:Index=\"11\" ss:AutoFitWidth=\"0\" ss:Width=\"39.75\"/>\n" .
       
  1009 "   <Column ss:Index=\"13\" ss:AutoFitWidth=\"0\" ss:Width=\"26.25\"/>\n" .
       
  1010 "   <Column ss:AutoFitWidth=\"0\" ss:Width=\"15\"/>\n" .
       
  1011 "   <Column ss:AutoFitWidth=\"0\" ss:Width=\"525.75\"/>\n";
       
  1012 
       
  1013     $str =~ s/EXCELEXPANDEDROWCOUNT/$rowCount/;
       
  1014     return $str;
       
  1015 };
       
  1016 
       
  1017 sub XmlFooter 
       
  1018 {
       
  1019     return 
       
  1020 "  </Table>\n" .
       
  1021 "  <WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">\n" .
       
  1022 "   <Print>\n" .
       
  1023 "    <ValidPrinterInfo/>\n" .
       
  1024 "    <PaperSizeIndex>9</PaperSizeIndex>\n" .
       
  1025 "    <HorizontalResolution>600</HorizontalResolution>\n" .
       
  1026 "    <VerticalResolution>600</VerticalResolution>\n" .
       
  1027 "   </Print>\n" .
       
  1028 "   <Selected/>\n" .
       
  1029 "   <Panes>\n" .
       
  1030 "    <Pane>\n" .
       
  1031 "     <Number>3</Number>\n" .
       
  1032 "     <ActiveRow>1</ActiveRow>\n" .
       
  1033 "     <RangeSelection>R2C1:R2C14</RangeSelection>\n" .
       
  1034 "    </Pane>\n" .
       
  1035 "   </Panes>\n" .
       
  1036 "   <ProtectObjects>False</ProtectObjects>\n" .
       
  1037 "   <ProtectScenarios>False</ProtectScenarios>\n" .
       
  1038 "  </WorksheetOptions>\n" .
       
  1039 " </Worksheet>\n" .
       
  1040 "</Workbook>\n";
       
  1041 }
       
  1042 
       
  1043 sub XmlEmptyRow 
       
  1044 {
       
  1045     return
       
  1046 "   <Row>\n" .
       
  1047 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"13\" ss:StyleID=\"s109\"><Data ss:Type=\"String\"></Data></Cell>\n" .
       
  1048 "   </Row>\n";
       
  1049 }
       
  1050 
       
  1051 sub XmlSwHwRow
       
  1052 {
       
  1053     return 
       
  1054 "   <Row>\n" .
       
  1055 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"13\" ss:StyleID=\"s111\"><Data ss:Type=\"String\">REPLACE</Data></Cell>\n" .
       
  1056 "   </Row>\n";
       
  1057 }
       
  1058 
       
  1059 sub XmlMetrics
       
  1060 {
       
  1061     return
       
  1062 "   <Row>\n" .
       
  1063 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"2\" ss:StyleID=\"s24\"><Data ss:Type=\"String\">Test Execution Metrics</Data></Cell>\n" .
       
  1064 "    <Cell ss:MergeAcross=\"10\" ss:StyleID=\"s27\"/>\n" .
       
  1065 "   </Row>\n" .
       
  1066 "   <Row>\n" .
       
  1067 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"1\" ss:StyleID=\"m153895744\"><Data ss:Type=\"String\">Total cases</Data></Cell>\n" .
       
  1068 "    <Cell ss:StyleID=\"s32\"><Data ss:Type=\"Number\">TOTALCASECOUNT</Data></Cell>\n" .
       
  1069 "    <Cell ss:MergeAcross=\"10\" ss:StyleID=\"s27\"/>\n" .
       
  1070 "   </Row>\n" .
       
  1071 "   <Row>\n" .
       
  1072 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"1\" ss:StyleID=\"s34\"><Data ss:Type=\"String\">Passed</Data></Cell>\n" .
       
  1073 "    <Cell ss:StyleID=\"s32\"><Data ss:Type=\"Number\">PASSEDCASECOUNT</Data></Cell>\n" .
       
  1074 "    <Cell ss:MergeAcross=\"10\" ss:StyleID=\"s27\"/>\n" .
       
  1075 "   </Row>\n" .
       
  1076 "   <Row>\n" .
       
  1077 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"1\" ss:StyleID=\"s34\"><Data ss:Type=\"String\">Failed</Data></Cell>\n" .
       
  1078 "    <Cell ss:StyleID=\"s32\"><Data ss:Type=\"Number\">FAILEDCASECOUNT</Data></Cell>\n" .
       
  1079 "    <Cell ss:MergeAcross=\"10\" ss:StyleID=\"s27\"/>\n" .
       
  1080 "   </Row>\n" .
       
  1081 "   <Row>\n" .
       
  1082 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"1\" ss:StyleID=\"s34\"><Data ss:Type=\"String\">Skipped</Data></Cell>\n" .
       
  1083 "    <Cell ss:StyleID=\"s32\"><Data ss:Type=\"Number\">SKIPPEDCASECOUNT</Data></Cell>\n" .
       
  1084 "    <Cell ss:MergeAcross=\"10\" ss:StyleID=\"s27\"/>\n" .
       
  1085 "   </Row>\n" .
       
  1086 "   <Row>\n" .
       
  1087 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"1\" ss:StyleID=\"s34\"><Data ss:Type=\"String\">Pass rate % (total cases)</Data></Cell>\n" .
       
  1088 "    <Cell ss:StyleID=\"s35\"><Data ss:Type=\"Number\">PASSRATEOFTOTAL</Data></Cell>\n" .
       
  1089 "    <Cell ss:MergeAcross=\"10\" ss:StyleID=\"s27\"/>\n" .
       
  1090 "   </Row>\n" .
       
  1091 "   <Row>\n" .
       
  1092 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"1\" ss:StyleID=\"s34\"><Data ss:Type=\"String\">Pass rate % (run cases)</Data></Cell>\n" .
       
  1093 "    <Cell ss:StyleID=\"s35\"><Data ss:Type=\"Number\">PASSRATEOFRUN</Data></Cell>\n" .
       
  1094 "    <Cell ss:MergeAcross=\"10\" ss:StyleID=\"s27\"/>\n" .
       
  1095 "   </Row>\n" .
       
  1096 "   <Row>\n" .
       
  1097 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"1\" ss:StyleID=\"m153881376\"><Data ss:Type=\"String\">Run rate %</Data></Cell>\n" .
       
  1098 "    <Cell ss:StyleID=\"s35\"><Data ss:Type=\"Number\">RUNRATE</Data></Cell>\n" .
       
  1099 "    <Cell ss:MergeAcross=\"10\" ss:StyleID=\"s27\"/>\n" .
       
  1100 "   </Row>\n";
       
  1101 }
       
  1102 
       
  1103 sub XmlTitleOnBlueRow 
       
  1104 {
       
  1105     return
       
  1106 "   <Row>\n" .
       
  1107 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"4\" ss:StyleID=\"m153881436\"><Data ss:Type=\"String\">THETITLE</Data></Cell>\n" .
       
  1108 "    <Cell ss:MergeAcross=\"8\" ss:StyleID=\"s119\"/>\n" .
       
  1109 "   </Row>\n";
       
  1110 }
       
  1111 
       
  1112 sub XmlTestNameRow
       
  1113 {
       
  1114     return
       
  1115 "   <Row>\n" .
       
  1116 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"2\" ss:StyleID=\"m153896384\"><Data ss:Type=\"String\">TESTNAME</Data></Cell>\n" .
       
  1117 "    <Cell ss:MergeAcross=\"1\" ss:StyleID=\"m153881708\"><Data ss:Type=\"String\">TESTRESULT</Data></Cell>\n" .
       
  1118 "    <Cell ss:MergeAcross=\"8\" ss:StyleID=\"s119\"/>\n" .
       
  1119 "   </Row>\n";
       
  1120 }
       
  1121 
       
  1122 sub XmlMessageRow
       
  1123 {
       
  1124     return
       
  1125 "   <Row>\n" .
       
  1126 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"4\" ss:StyleID=\"m153896384\"><Data ss:Type=\"String\">MESSAGE</Data></Cell>\n" .
       
  1127 "    <Cell ss:MergeAcross=\"8\" ss:StyleID=\"s119\"/>\n" .
       
  1128 "   </Row>\n";
       
  1129 }
       
  1130 
       
  1131 sub XmlPassedCaseRow
       
  1132 {
       
  1133     return
       
  1134 "   <Row>\n" .
       
  1135 "    <Cell ss:Index=\"2\" ss:StyleID=\"s48\"><Data ss:Type=\"String\">PASSED</Data></Cell>\n" .
       
  1136 "    <Cell ss:MergeAcross=\"3\" ss:StyleID=\"m153881708\"><Data ss:Type=\"String\">TESTCASENAME</Data></Cell>\n" .
       
  1137 "    <Cell ss:MergeAcross=\"8\" ss:StyleID=\"s119\"/>\n" .
       
  1138 "   </Row>\n";
       
  1139 }
       
  1140 
       
  1141 sub XmlFailedCaseRow 
       
  1142 {
       
  1143     return 
       
  1144 "   <Row>\n" .
       
  1145 "    <Cell ss:Index=\"2\" ss:MergeDown=\"1\" ss:StyleID=\"m153895896\"><Data ss:Type=\"String\">FAILED</Data></Cell>\n" .
       
  1146 "    <Cell ss:MergeAcross=\"2\" ss:MergeDown=\"1\" ss:StyleID=\"m153895906\"><Data\n" .
       
  1147 "      ss:Type=\"String\">TESTCASENAME</Data></Cell>\n" .
       
  1148 "    <Cell ss:MergeDown=\"1\" ss:StyleID=\"m153896394\"><Data ss:Type=\"String\">FAILREASON</Data></Cell>\n" .
       
  1149 "    <Cell ss:MergeAcross=\"8\" ss:StyleID=\"s119\"/>\n" .
       
  1150 "   </Row>\n" .
       
  1151 "   <Row>\n" .
       
  1152 "    <Cell ss:Index=\"7\" ss:MergeAcross=\"8\" ss:StyleID=\"s119\"/>\n" .
       
  1153 "   </Row>\n";
       
  1154 }
       
  1155 
       
  1156 sub XmlTextRowRed
       
  1157 {
       
  1158     return
       
  1159 "   <Row>\n" .
       
  1160 "    <Cell ss:Index=\"2\" ss:StyleID=\"redbg\"><Data ss:Type=\"String\"></Data></Cell>\n" .
       
  1161 "    <Cell ss:MergeAcross=\"3\" ss:StyleID=\"m153881708\"><Data ss:Type=\"String\">REPLACE</Data></Cell>\n" .
       
  1162 "    <Cell ss:MergeAcross=\"8\" ss:StyleID=\"s119\"/>\n" .
       
  1163 "   </Row>\n";
       
  1164 }
       
  1165 
       
  1166 sub XmlTextRowRedx
       
  1167 {
       
  1168     return 
       
  1169 "   <Row>\n" .
       
  1170 "    <Cell ss:Index=\"2\" ss:MergeAcross=\"8\" ss:StyleID=\"REDTEXT\"><Data ss:Type=\"String\">REPLACE</Data></Cell>\n" .
       
  1171 "   </Row>\n";
       
  1172 }