#!/usr/bin/perl
#----------------------------->  Perl - script  <-----------------------------#
#- Copyright (C) 199x by International Computer Science Institute            -#
#- This file is part of the GNU Sather package. It is free software; you may -#
#- redistribute  and/or modify it under the terms of the  GNU General Public -#
#- License (GPL)  as  published  by the  Free  Software  Foundation;  either -#
#- version 2 of the license, or (at your option) any later version.          -#
#- This  program  is distributed  in the  hope that it will  be  useful, but -#
#- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY -#
#- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/GPL for more details.        -#
#- The license text is also available from:  Free Software Foundation, Inc., -#
#- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     -#
#------------->  Please email comments to <bug-sather@gnu.org>  <-------------#

# Test the Sather Compiler
#
# This script tests the compiler by compiling it with itself with different
# options and the using those compilers to compiler the Test classes.
#
# It assumes that the compiler it in the directory ./Compiler,
# the boot compiler in the directory ./Boot and the Test classes
# in ./Test. It sets the environment variable SATHER_HOME to the current
# directory. It will create a new directory TEST in the current
# directory and store the results and all intermediate compiler 
# versions and test classes there. If there is already a directory
# TEST it will be renamed to TEST.#. For all compilations it uses
# the flags -C_flag -g -pretty -output_C
#
# Arguments: it accepts one of the following arguments:
# 	     -f --fast      for a quick and dirty test 
#	     -s --standard  for the standard test (this is the default)
#	     -x --extensive for the extensive test.
#	     -e --ieee      test for ieee conformance.
#	     -c --C	    keep the source of all compilations
#	     -n		    just print the commands without executing them
#	     platform [platforms]  The script accepts also a list of
#				   platforms. By default it will only check
#				   the standard platform, and assumes that 
#				   this platform is suitable to compile 
#				   the compiler on it.
#		pSather platforms are tested with the last compiler build for
#		the last platform that is not a pSather platform. If there
#		is no such platform, the script uses the boot compiler.
#
# This script can run unattended, but you may not have more than one
# of this script running in the same directory at the same time.
#
# It writes the result to the standard output and appends it to the file
# cs.test_results in TEST
#
# Version 1.1 by CMF, September 1995
#
# How it works:
# The script assumes that the boot compiler has been compiled, and
# that all necessary files and libraries are there.
#
# -f:	Compile the compiler with the boot compiler and the options 
#	  -chk -o cs1
#	Compiler the compiler with cs1 and the options
#	  -O_fast -o cs2
#	Compile and check the test classes with cs2 and the options
#	  -O_fast -o t1
#
# -s:	Compile the compiler with the boot compiler and the options 
#	  -chk -o cs1x
#	Compiler the compiler with cs1x and the options
#	  -chk -o cs1
#	Compiler the compiler with cs1 and the options
#	  -O_fast -o cs2
#	Compile and check the test classes with cs2 and the options
#	  -chk  -o t1
#	Compile and check the test classes with cs2 and the options
#	  -O_fast -o t2
#
# -x:	Compile the compiler with the boot compiler and the options 
#	  -chk -o cs1x
#	Compiler the compiler with cs1x and the options
#	  -chk -o cs1y
#	Compiler the compiler with cs1x and the optionsy
#	  -chk -o cs1
#	Compiler the compiler with cs1 and the options
#	  -O_fast -o cs2x
#	Compiler the compiler with cs2x and the options
#	  -O_fast -o cs2
#	Compile and check the test classes with cs1 and the options
#	  -chk -o t1
#	Compile and check the test classes with cs1 and the options
#	  -O_fast -o t2
#	Compile and check the test classes with cs2 and the options
#	  -chk -o t3
#	Compile and check the test classes with cs2 and the options
#	  -O_fast -o t4
#

$CSFLAGS="-output_C -pretty -verbose";
$CHECKFLAGS="-chk";
$FASTFLAGS="-O_fast ";
$PSATHERFLAGS="";
$PWD=`pwd`;
if($PWD =~ /^\/xa\//) {
	$PWD="/n/$ENV{'HOST'}$PWD";
} else {
	$PWD=`uwd`; # uwd is a special version of pwd used at ICSI
} 
chop $PWD;

$ENV{'SATHER_HOME'}=$PWD;
delete $ENV{'SATHER_LIBRARY'};
delete $ENV{'PSATHER_LIBRARY'};
delete $ENV{'DEBUG_PSATHER'};
delete $ENV{'DEBUG_AM'};
delete $ENV{'START_GDB'};
$TESTDIR="$PWD/TEST";
$BOOTCS="$PWD/Boot/sacomp";
$TESTRESULT="$TESTDIR/test.result";
$type='std';
$USAGE="$0 [-f|-s|-x|--fast|--standard|--extensive] [-c] [-e] platforms\n";
$OUTFILE="$TESTDIR/out";
$MAKE="pmake -s -J 20 -L -1";
$testclass="test-all.module";
$ptestclass="test-psather.module";
$ztestclass="test-zones.module";
$keepC=0;
$no_exec=0;
%Title= ( 'std','Standard Test','fast','Quick and Dirty Test',
          'ext','Extensive Test' );

if(! -d "Boot" || ! -d "Test" || ! -d "Compiler") {
	die "$0: you must start this program in the Sather Home directory\n";
}
while(@ARGV>0) {
	DONE: {
		($ARGV[0] =~ /^(-f)|(--fast)$/) && do { $type='fast';last DONE; };
		($ARGV[0] =~ /^(-s)|(--standard)$/) && do { $type='std';last DONE; };
		($ARGV[0] =~ /^(-x)|(--extensive)$/) && do { $type='ext';last DONE; };
		($ARGV[0] =~ /^(-e)|(--ieee)$/) && do { $testclass='test-all.module';last DONE; };
		($ARGV[0] =~ /^(-c)|(--C)$/) && do { $keepC=1;last DONE; };
		($ARGV[0] =~ /^(-n)$/) && do { $no_exec=1;last DONE; };
		push(platforms,$ARGV[0]);
	}
	shift;
}
! -x $BOOTCS && die "cannot find the boot compiler $BOOTCS";
$i=0;

sub mk_testdir {
	while(-d $TESTDIR) {
		$i++;
		if((! -d $TESTDIR.".$i") && (!-e $TESTDIR.".$i")) {
			rename($TESTDIR,$TESTDIR.".$i") || 
			   die "cannot rename $TESTDIR to $TESTDIR.$i, $!\n";
			if($i>10) {
				print "you have now $i TEST directories, maybe you should clean them up.\n";
			}
		}
	}
	mkdir($TESTDIR,0755) || die "cannot create directory $TESTDIR, $!\n";
}
sub open_result {
	if(! -f $TESTRESULT) {
		open (RESULT,">$TESTRESULT") || die "cannot open the file $TESTRESULT for writing, $!\n";
	} else {
		open (RESULT,">>$TESTRESULT") || die "cannot open the file $TESTRESULT for appending, $!\n";
	}
}

sub close_result {
	close RESULT;
}

sub get_platforms {
	if($#platforms<0) { 
		open(CONFIG,"System/Common/CONFIG") || die "cannot open System/Common/CONFIG, $!\n";
		while(<CONFIG>) {
			if(/DEFAULT_PLATFORM:[ \t"]*([^"; ,]*)/) {
				push(platforms,$1);
				last;
			}
		}
		close(CONFIG);
		$#platforms<0 && die "cannot find DEFAULT_PLATFORM in System/Common/CONFIG\n";
	}

	$i=0;
	foreach $platform (@platforms) {
		$t="System/Platforms/".$platform."/CONFIG";
		open(CONFIG,$t) || die "cannot open $t, $!\n";
		$threads[$i]=0;
		$distributed[$i]=0;
		$zones[$i]=0;
		$clusters[$i]=3;
		while(<CONFIG>) {
			/THREADS:.*true/ && ($threads[$i]=1);
			/DISTRIBUTED:.*true/ && ($distributed[$i]=1);
			/ZONES:.*true/ && ($zones[$i]=1);
			/MAX_CLUSTERS:[^0-9]*([0-9]*)/ && ($clusters[$i]=$1);
		}
		close(CONFIG);
		$thread="";
		$zone="";
		$dist="";
		$cluster="";
		$threads[$i]==1 && ($thread="X");
		$zones[$i]==1 && ($zone="X");
		$distributed[$i]==1 && ($dist="X", $cluster=$clusters[$i]);
		$~="RESULT";
		write;
		write(RESULT);
		$i++;
	}
	print "\n";
	format RESULT_TOP =
SATHER/PSATHER COMPILER TEST FOR

Platform                     Threads  Distributed  Clusters  Zones
------------------------------------------------------------------
.
	format RESULT =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<   @|         @|          @|      @|
$platform                       $thread    $dist     $cluster $zone
.
}


sub compile {
	local($compiler,$platform,$options,$dir,$filename,$output_name) = @_;
	if($compiler ne $BOOTCS) { $compiler="$TESTDIR/$compiler"; }
	if(-d "$TESTDIR/$output_name.code") { system "rm -rf $TESTDIR/$output_name.code"; } 
	if(-d "$TESTDIR/$output_name") { unlink "$TESTDIR/$output_name"; } 
	print RESULT "-------------------------------------------------------\n";
	print RESULT "Compiling:     $dir/$filename\n";
	print RESULT "Options:       -$platform $options\n";
	print RESULT "Compiler used: $compiler\n";
	print RESULT "SATHER_HOME:   $ENV{'SATHER_HOME'}\n";
	print RESULT "Out File:      $output_name\n";
	$exec="$compiler -$platform $CSFLAGS $options -only_C -o $TESTDIR/$output_name $filename";
	print RESULT "EXECUTING: $exec\n";
	print "$exec\n";
	&close_result;
	if($no_exec==1) { return; }
	$a=system("cd $dir ; $exec >> $TESTRESULT 2>&1");
	&open_result;
	if($a/256!=0 || ! -e "$TESTDIR/$output_name.code/Makefile") {
		print "The compilation failed, please check the file $TESTRESULT for more information\n";
		print RESULT "The compilation failed, aborting\n";
		exit 1;
	}
	$exec2="cd $TESTDIR/$output_name.code; $MAKE >> $TESTRESULT 2>&1 ; $MAKE >> $TESTRESULT 2>&1";
	if($keepC == 0) { $exec2.="; cd .. ; rm -r $output_name.code"; }
	else { $exec2.="; rm *.o"; }
	print RESULT "$exec2\n";
	&close_result;
	system "$exec2";
	&open_result;
	if(! -x "$TESTDIR/$output_name") {
		print "The compilation failed, please check the file $TESTRESULT for more information\n";
		print RESULT "The compilation failed, aborting\n";
		exit 1;
	}
}

sub compilecs {
	local($compiler,$platform,$options,$output_name) = @_;
	&compile($compiler,$platform,$options,"Compiler","sacomp.module",$output_name);
}

sub testclass {
	local($compiler,$platform,$options,$file,$output_name) = @_;
	&compile($compiler,$platform,$options,"Test",$file,$output_name);
	&close_result;
	if($no_exec==1) { return; }
	system("$TESTDIR/$output_name > $TESTDIR/$output_name.out 2> $TESTDIR/$output_name.err; cat $TESTDIR/$output_name.err >> $TESTRESULT");
	&open_result;
	open(CHECK,"$TESTDIR/$output_name.err");
	$done=0;
	while(<CHECK>) {
		if(/failed/) {
			print "The test classes have failed, please check\nthe files $TESTRESULT, $output_name.err and $output_name.out for more information\n";
			print RESULT "The test classes have failed, please check\nthe files $TESTRESULT, $output_name.err and $output_name.out for more information\n";
			exit 1;
		}
		if(/TEST DONE$/) { $done=1; }
	}
	if($done==0) {
		print "The test classes have failed, please check\nthe files $TESTRESULT, $output_name.err and $output_name.out for more information\n";
		print RESULT "The test classes have failed, please check\nthe files $TESTRESULT, $output_name.err and $output_name.out for more information\n";
		exit 1;
	}
	close(CHECK);
	$keepC==0 && unlink("$TESTDIR/$output_name");
}


&mk_testdir;
&open_result;
&get_platforms;
$ENV{'CLUSTERS'}=3;

$PSCS=$BOOTCS;
for($i=0;$i<=$#platforms;$i++) {
	print "\nworking on $platforms[$i]\n";
	if($threads[$i]==0) { # standard Sather
		if($type eq "fast") {
			&compilecs($BOOTCS,$platforms[$i],$CHECKFLAGS,"cs1");
			&compilecs("cs1",$platforms[$i],$FASTFLAGS,"cs2");
			&testclass("cs2",$platforms[$i],"$CHECKFLAGS -debug",$testclass,"test1c");
			&testclass("cs2",$platforms[$i],$FASTFLAGS,$testclass,"test1f");
###			$a=system("cd Test/TestPrg ; PROG/do_all QUICK $ENV{'SATHER_HOME'}/TEST/cs2");
###			if($a/256!=0) { die "some testprogram failed";}
		} elsif($type eq "std") {
			&compilecs($BOOTCS,$platforms[$i],$CHECKFLAGS,"cs1x");
			&compilecs("cs1x",$platforms[$i],$CHECKFLAGS,"cs1");
			$keepC==0 && unlink("$TESTDIR/cs1x");
			if($zones[$i]==1) {
				&testclass("cs1",$platforms[$i],"$CHECKFLAGS -debug",$ztestclass,"testzones");
				&testclass("cs1",$platforms[$i],"$FASTFLAGS",$ztestclass,"testzones2");
			}
			&testclass("cs1",$platforms[$i],$CHECKFLAGS,$testclass,"test1c");
			&testclass("cs1",$platforms[$i],$FASTFLAGS,$testclass,"test1f");
			&compilecs("cs1",$platforms[$i],$FASTFLAGS,"cs2");
			&testclass("cs2",$platforms[$i],"$CHECKFLAGS -debug",$testclass,"test2c");
			&testclass("cs2",$platforms[$i],$FASTFLAGS,$testclass,"test2f");
###			$a=system("cd Test/TestPrg ; PROG/do_all STD $ENV{'SATHER_HOME'}/TEST/cs2");
###			if($a/256!=0) { die "some testprogram failed";}
		} elsif($type eq "ext") {
			&compilecs($BOOTCS,$platforms[$i],$CHECKFLAGS,"cs1x");
			&compilecs("cs1x",$platforms[$i],$CHECKFLAGS,"cs1y");
			$keepC==0 && unlink("$TESTDIR/cs1x");
			&compilecs("cs1y",$platforms[$i],$CHECKFLAGS,"cs1");
			$keepC==0 && unlink("$TESTDIR/cs1y");
			&testclass("cs1",$platforms[$i],$CHECKFLAGS,$testclass,"test1c");
			&testclass("cs1",$platforms[$i],$FASTFLAGS,$testclass,"test1f");
			&compilecs("cs1",$platforms[$i],$FASTFLAGS,"cs2x");
			&compilecs("cs2x",$platforms[$i],$FASTFLAGS,"cs2");
			$keepC==0 && unlink("$TESTDIR/cs2x");
			&testclass("cs2",$platforms[$i],$CHECKFLAGS,"$testclass -debug","test2c");
			&testclass("cs2",$platforms[$i],$FASTFLAGS,$testclass,"test2f");
###			$a=system("cd Test/TestPrg ; PROG/do_all EXT $ENV{'SATHER_HOME'}/TEST/cs2");
###			if($a/256!=0) { die "some testprogram failed";}
		}
		$PSCS="cs2";
	} else {
	        $ENV{'CLUSTERS'}=3;
	        $ENV{'SATHER_NODES'}="icsib78 samosa icsib18";
		if($type eq "fast") {
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $CHECKFLAGS",$testclass,"test1pf");
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $CHECKFLAGS",$ptestclass,"test1pf");
		} elsif($type eq "std") {
			if($zones[$i]==1) {
				&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $CHECKFLAGS -debug",$ztestclass,"testzones");
				&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $FASTFLAGS",$ztestclass,"testzones2");
			}
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $CHECKFLAGS -debug",$testclass,"test2pf");
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $CHECKFLAGS -debug",$ptestclass,"test1pf");
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $FASTFLAGS",$testclass,"test2pf");
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $FASTFLAGS",$ptestclass,"test1pf");
		} elsif($type eq "ext") {
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $CHECKFLAGS -debug",$testclass,"test2pf");
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $CHECKFLAGS -debug",$ptestclass,"test1pf");
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $FASTFLAGS",$testclass,"test2pf");
			&testclass($PSCS,$platforms[$i],"$PSATHERFLAGS $FASTFLAGS",$ptestclass,"test1pf");
		}
	}
}

$no_exec==0 && print "THERE WERE NO ERRORS, EVERYTHING WORKED FINE\n";
exit 0;






