#!/usr/bin/env perl
use strict;
use warnings;
local $| = 1 ;

# --------------------------------------------------------
# Prototype runtool, this version will generate Nx JUnit test-classes.
# --------------------------------------------------------

# --------------------------------------------------------
# Few thing that may need to be re-cofigured
# --------------------------------------------------------

my $MYlaptop = 9 ;
my $UPV = 0 ;
my $deploy = $MYlaptop ;
#my $deploy = $UPV ;

my $MYHOME = "/home/t2" ; 
my $JAVA = "/usr/lib/jvm/java-8-oracle/bin/java" ;
my $CPseparator = ":" ;

if ($deploy == $MYlaptop) { 
    $MYHOME = "." ; 
    $JAVA  = "/cygdrive/c/apps/Java/jdk1.8.0/bin/java" ;
    $CPseparator = ";" ;
}
     
# derived paths, no need to change this
my $T3JAR = $MYHOME . "/jars/T3v0.jar" ;
#my $ALLJARS = $MYHOME . "/jars" ;

# --------------------------------------------------------
# Some help-functions first ...
# --------------------------------------------------------

sub debugEcho {
    print "[debug] " . $_[0]
}

sub mkTempDirs {
   debugEcho "creating temp-dirs" ;
   my $DATADir = $MYHOME . "/temp/data" ;
   my $testcasesDir = $MYHOME . "/temp/testcases" ;
   if (!(-e $DATADir)) {
      system("mkdir -p " . $DATADir) ;
   }
   if (!(-e $testcasesDir)) {
      system("mkdir -p " . $testcasesDir) ;
   }
}

sub BENCHMARKtoken {
   my $token = readline(*STDIN) ; chomp $token ;
   if ($token ne "BENCHMARK") { 
      print STDERR "ERROR: expecting BENCHMARK token" ;
      exit 0 ;
   }
}

sub readPath {
  my $t = <STDIN> ; chomp $t ; return $t ;
}
 
sub readNum {
  my $N = <STDIN> ; chomp $N ;
  return 0 + $N ;
} 
  
sub readContextClassPaths {
  my $N = $_[0] ;
  my $paths = "." ;
  my $k ;
  for ($k=0; $k<$N; $k++) {
     my $p = <STDIN> ;
     chomp $p ;
     $paths = $paths . $CPseparator ; 
     $paths = $paths . $p ;
  }
  return $paths ;
}
 
# for passing the path to T2-jar .. not sure if this is a good way
# to do it.
sub announcePathToTestingTool {
   print "CLASSPATH\n" ;
   #print "2\n" ;
   #print ($T2JAR . "\n") ;
   #print ($ALLJARS . "\n") ;
   print "1\n" ;
   print ($T3JAR . "\n") ;
   print ("READY\n") ;
}


# replaceIt(s,a,b) replaces occurences of string a in string s, with b
sub replaceIt {
   my $str     = $_[0] ;
   my $find    = $_[1];
   my $replace = $_[2] ;
   # escape regex metachars if present:
   $find    = quotemeta $find; 
   $replace = quotemeta $replace; 
   $str =~ s/$find/$replace/g ;
   return $str ;
}      

# as replaceIt, but without replcing metachars:
sub replaceIt2 {
   my $str     = $_[0] ;
   my $find    = $_[1];
   my $replace = $_[2] ;
   $str =~ s/$find/$replace/g ;
   return $str ;
}
   

my $NUMofTestClasses = 5 ;
   
# For creating a Junit test-class wrapper
sub mkJunit {
    my $CUT = $_[0] ;
    my $CUTdashed = replaceIt($CUT,".","_") ;
    my $template  = $MYHOME . "/T3TestClassWrapper_TC_Template.java" ;  
    
    open (TemplateFile,"<",$template);
    
    # read the template Test-class:
    my $Test = "" ;
    while (<TemplateFile>) { $Test = $Test . $_ ; }
    close (TemplateFile); 
    
    # now, generate Nx test-classes
    my $k=0 ;
    while ($k < $NUMofTestClasses) {
       my $testclassName = "TEST_S" . $k ;
       my $testclass     = $MYHOME . "/temp/testcases/" . $testclassName . ".java" ;
       open (TestClassFile,">",$testclass) ;
       my $Instance = replaceIt2($Test, "xxxClass", $testclassName) ;  
       $Instance= replaceIt2($Instance,"xxxSuite", "T3suite_S" . $k) ;
       $Instance = replaceIt2($Instance,"xxxLog"  , $MYHOME . "/logs/REPLAY_" . $CUT . "_S" . $k) ;
       $Instance = replaceIt2($Instance,"xxxTargetDir"  , $MYHOME . "/temp/testcases/") ; 
       print TestClassFile $Instance ;
       close (TestClassFile) ;
       $k ++ ;
    }  
}
 


# to run T3; runT3(CUT,class-dir of CUT, class-path context) 
sub runT3 {
   my $CUT = $_[0] ;
   # the root of the class-directory where CUT resides
   my $CUTdir = $_[1] ;
   # class-path to stuffs needed to run CUT:
   my $contextClassPath = $_[2] ;
   
   my $T3 = " Sequenic.T3.T3 "  ;

   my $LOG = $MYHOME  . "/logs/GEN_" . $CUT ;
   
   my $T3params = "--multicore " 
                . "--nonviolating "
                . "--prefixlength=7 --suffixlength=0 "
                . "--msamples=120 "
                . "--trfile=T3suite "
                . "--splitsuite=" . $NUMofTestClasses . " "
                . "--savedir=" . $MYHOME . "/temp/testcases "
                . "--scandir=" . $CUTdir . " " 
                . " -lf " . $LOG  . " " ;
                
   my $classpath = "\'" 
            . $T3JAR . $CPseparator 
            . $CUTdir . $CPseparator . $contextClassPath
            . "\'" ;
            
   
   # now calling T3:
   system(
     $JAVA . " -ea -cp " . $classpath . " "
         . $T3 . " " 
         . $T3params 
         . " " . $CUT
    ) ;
    # now generate Junit wrapper too, to prepare for replay:
    mkJunit($CUT) ;
}

# run T3 n-times, for each of n CUTs
sub runLoop {
   my $N      = $_[0] ;
   my $CUTdir = $_[1] ;
   my $contextClassPath = $_[2] ;
   
   my $k ;
   for ($k=0; $k<$N; $k++) {
      mkTempDirs() ;
      my $CUT = <STDIN> ; chomp $CUT ;
      runT3($CUT,$CUTdir,$contextClassPath) ;
      print ("READY\n") ;
   }
}

# --------------------------------------------------------
# Here begins the protocol
# --------------------------------------------------------
 
debugEcho "SBST protocol START\n";
BENCHMARKtoken() ;
my $src = readPath() ;
my $bin = readPath();
my $numOfContextClassPaths  = readNum() ;
my $contextClassPath = readContextClassPaths($numOfContextClassPaths) ;
my $numOfTargetClasses = readNum() ;
announcePathToTestingTool() ;
# Now the protocol is going to pass N x CUTs; we run T3 on each of them:
runLoop($numOfTargetClasses,$bin,$contextClassPath) ;
# DONE.
debugEcho "SBST protocol END" ;
endDEBUG() ;

sub endDEBUG {
   debugEcho ("src = " . $src . "\n") ;
   debugEcho ("bin = " . $bin . "\n") ;
   debugEcho ("N = " . ($numOfContextClassPaths + 1 - 1) . "\n") ;
}
