#!/usr/bin/perl

#LTP results gathering script: ltp_check
#       3/12/02 William Jay Huie (creation)
#       3/28/02 William Jay Huie minor fixes, increased results parsing
#       5/01/02 William Jay Huie parsing changes
#       5/17/02 Casey Abell added sar results
#This will log into the LTP_HOST machine, which may be different then the
#machine used to run the ltp_master script
#This script will check for *ltpoutput.tgz files created by the ltprun script
#and download them each to their own directory and do a bit of processing
#the results gathering probably needs to be extended but hopefully this is a good
#first go at it

use Net::FTP ();

#CHANGEME:
#For some reason doesn't work if you do ~/ltp/results, so you need to code the
#explicit path for LTP_RES_DIR unless someone can tell me why
$LTP_RES_DIR="/home/wjhuie/ltp/results";
#CHANGEME:
$LTP_HOST="ltp_host.somewhere.org";

#This is who has the *ltpoutput.tgz files, where the results are uploaded
#     not necessarially the user id that ran the test
$LTP_USER="ltp";
$LTP_PASS="ltp";
$LTP_LOGFILE="ltp-logfile";
$LTP_RUN_OUTPUT="ltprun.out";
$LTP_RUNALL_OUT="runall.output";
$RESULTS_OUT="results.out";
$FAILS_OUT="failures.list";
$SAR_OUTFILE="sar.data";

@res_dirs;
$count = 0;
$RES = 0;
$FAILS = 0;
%hash;

sub download_results()
{
   print "Attempting to download the LTP results\n";

   $dir = system("ls $LTP_RES_DIR &> /dev/null") / 256;
   if ($dir)
   {
     print "Making a results directory in $LTP_RES_DIR\n";
     `mkdir -p $LTP_RES_DIR`;
     chdir "$LTP_RES_DIR" or die "Can't change to $LTP_RES_DIR\n";
   }
   else
   { chdir "$LTP_RES_DIR" or die "Can't change to $LTP_RES_DIR\n"; }

   $ftp = Net::FTP->new($LTP_HOST, Debug => 0) or die "Can't connect to ftp: $LTP_HOST";
   $ftp->login($LTP_USER, $LTP_PASS) or die "Unable to login";
   $ftp->type('I') or die "Unable to set type to Binary";
   @files = $ftp->ls("*ltpoutput.tgz");
   $num_files = $#files + 1;
   print "New results files found $num_files:\n";
   for ($i = 0; $i < $num_files; $i++) { print "\t$files[$i]\n"; }

   for ($i = 0; $i < $num_files; $i++)
   {
      print "Downloading: $files[$i]\t";
      if ($ftp->get($files[$i]))
      {
         print "Successful\n";
         $ftp->delete($files[$i]);
      }
      else
      { print "FAILED\n"; }

   }
   $ftp->quit;

   @res = `ls $LTP_RES_DIR/*.tgz 2> /dev/null`;

   if (@res)
   {
      $num = $#res + 1;
      print "             download of LTP results finished\n";
      print "$num unprocessed results files found\n";
      chomp(@res);
      return 1;
   }
   else
   {  print "             no apparent results to process\n"; return 0; }

}

sub untar_results()
{
   for ($i = 0; $i < $num; $i++)
   {
      if ( $res[$i] =~ m/\s*(\w+)-((\w+)-)*ltpoutput.tgz/ )
      {
         $hostname = $1;
         $epoch_time = $3;
         $english_time = localtime($epoch_time);
         $dir = "$LTP_RES_DIR/$hostname/$english_time";

         if ($english_time)
         {
            $new_dir = $dir;
            $new_dir =~ s/ /_/g;
            print "New results: $hostname @ $english_time\n";
            `mkdir -p '$new_dir'`;
            chdir "$new_dir" or die "Can't change to $new_dir\n";
            `tar -zxf $res[$i]`;
            `mv $res[$i] $new_dir`;
            $res_dirs[$count] = $new_dir; $count++;
         }
         else
         {
            print "No timestamp on results file, skipping for now\n";
#Should come up with a soultion for this, check/create $hostname
#     then some unique identifier but for now we'll complain and ignore
         }
      }
   }
   return 1;
}

sub gather_results()
{
   print "Gathering $count result(s):\n";

   for ($i = 0; $i < $count; $i++)
   {
      print "\nResults for: $res_dirs[$i]\n";
      chdir "$res_dirs[$i]" or die "Can't change to $res_dirs[$i]\n";

      if ( !( -f $LTP_RUNALL_OUT && -f $LTP_LOGFILE ) )
      {
           print "$LTP_RUNALL_OUT or $LTP_LOGFILE seems to be missing\n";
           print "     check the tarfile and perhaps $LTP_RUN_OUTPUT\n";
           print "Skipping\n";
           next;
      }

      chomp($stat = `tail -n 1 $LTP_RUNALL_OUT`);
      print "\t\t$stat\n";

      $num_success = `grep "stat=0" $LTP_LOGFILE | wc -l`;
      if ( $num_success =~ /\s*(\d+)\s*/ ) { $num_success = $1; }

      @fails = `grep "stat=" $LTP_LOGFILE | grep -v "stat=0"`;
      $num_fail = $#fails + 1;

      # gather the same fail cases together and have a counter for each different fail case.

        foreach $each (@fails) {
                if ($each =~ /(.)*tag=(\w+)\sstime=(.+)/){
                        $case = $2;
                        # print "$case\n";
                        if (exists $hash{$case}) {
                        #       print "$hash{$case} before\n";
                                $counter = $hash{$case}+1;
                                $hash{$case} = $counter;
                        #       print "$hash{$case} later\n";

                        }
                        else {
                                $hash{$case}=1;
                        }
                }
        }

      $pass_percent = sprintf("%.2f",
                         ($num_success / ($num_success + $num_fail)) * 100);

      $ltp_ver = `grep "version" $LTP_RUN_OUTPUT`;
      if ( $ltp_ver =~ m/.*version: (.*)/ ) { $ltp_ver = $1; }

      $line = "Pass $pass_percent % : $num_success succeeded : $num_fail failed";
      print "$line\n";

      $line1 = `sar -f $SAR_OUTFILE |tail -n 1`;
      if ($line1 =~ /(.+)/) {
        @sarstats1 = split(/\s+/, $line1);
        print "Cpu user = $sarstats1[2]%\n";
        print "Cpu nice = $sarstats1[3]%\n";
        print "Cpu system = $sarstats1[4]%\n";

        $line2 = `sar -r -f $SAR_OUTFILE |tail -n 1`;
        @sarstats2 = split(/\s+/, $line2);
        print "Memory used = $sarstats2[3]%\n";
        print "Swap used = $sarstats2[9]%\n";

        $line3 = `sar -c -f $SAR_OUTFILE |tail -n 1`;
        @sarstats3 = split(/\s+/, $line3);
        print "Processes created per second = $sarstats3[1]%\n";
      }

      if (open RES, ">$RESULTS_OUT")
      {
         print ". -> Results stored in $RESULTS_OUT\n";
         if (!open FAILS, ">$FAILS_OUT") { print "Error opening $FAILS_OUT\n"; }
         $num =
#The <<<test_start>>> doesn't always get into the runalltest.sh output capture
#because some output will appear before its corresponding block
#So for now relying on last thing from ver_linux to know when to stop copying
#          system("awk '/<<<test_start>>>/ { exit NR-1; }' $LTP_RUNALL_OUT") / 256;
           system("awk '/bogomips/ { exit NR; }' $LTP_RUNALL_OUT") / 256;

         @system_info = `head -n $num $LTP_RUNALL_OUT`;

         if ($ltp_ver) { print RES "$ltp_ver : "; }
         print RES "$line\n\n";
         if ($line1 =~ /(.+)/) {
           print RES "Cpu user = $sarstats1[2]%\n";
           print RES "Cpu nice = $sarstats1[3]%\n";
           print RES "Cpu system = $sarstats1[4]%\n";
           print RES "Memory used = $sarstats2[3]%\n";
           print RES "Swap used = $sarstats2[9]%\n";
           print RES "processes created per second = $sarstats3[1]%\n\n";
        }
         print RES "@system_info\n";
         print RES "$stat:\n";

         #print out each failed case information.
         foreach $case(keys %hash){
                print RES "failed case=$case\tnumber of failures=$hash{$case}\n";
         }
#end of new ouput section

         $runall = `cat $LTP_RUNALL_OUT`;

	 # reset hash table values to 0
	 foreach $case(keys %hash){
		$hash{$case}=0;
	 }

         for ($j = 0; $j < $num_fail; $j++)
         {
            if ( $fails[$j] =~ m/^tag=(\w+?) / )
            {
               	$test_case = $1;
		# each failure case will be printed out only once
	       	if ((exists $hash{$test_case})&&( $hash{$test_case}==0 )) {
			$hash{$test_case}=1;

                        if (FAILS) { print FAILS "$test_case\n"; }
               		print RES "\nTrying to find $test_case output";
               		if ( $runall =~
			#modified because some output is appearing before tagline
                    		m/((^$test_case.*?)*<<<test_start>>>.tag=$test_case.*?<<<test_end>>>)/ms )
               		{
               		   	print RES "\n-------------------------\n";
                 		print RES "$1";
                 		print RES "\n-------------------------\n";
               		}
              		else
               		{
                  		print RES "\n-------------------------\n";
                  		print RES "Unable to locate output for $test_case!";
                  		print RES "\n-------------------------\n";
               		}
		}
            }
         }
         close(RES); close(FAILS);
      }
      else
      { print "Can't open $RESULTS_OUT, test failures are:\n @fails\n"; }
   }
   return 1;
}

if (!download_results)
{ exit 0; }

if (!untar_results)
{ exit 0; }

if (!gather_results)
{ exit 0; }