#!/usr/bin/env perl # runtest [options] FILENAME # # Read the file FILENAME. Each line contains a test. # Convert template to test and crosstest. # If possilble generate orphaned testversions, too. # Use make to compile the test ################################################################################ # Global configuration options for the runtestscript itself: ################################################################################ # name of the global configuration file for the testsuite: $config_file = "ompts.conf"; $logfile = "ompts.log"; # overwriteable by value in config file $env_set_threads_command = 'OMP_NUM_THREADS=%n; export OMP_NUM_THREADS;'; $debug_mode = 0; ################################################################################ # After this line the script part begins! Do not edit anithing below ################################################################################ # Namespaces: use Getopt::Long; #use Unix::PID; use Data::Dumper; use ompts_parserFunctions; # Extracting given options GetOptions("help", "listlanguages", "lang=s", "list", "testinfo=s", "numthreads=i", "test=s", "compile!", "run!", "orphan!", "resultfile=s" ); # Get global configuratino options from config file: if(! -e $config_file){ error ("Could not find config file $config_file\n", 1);} open (CONFIG, "<$config_file") or error ("Could not open config file $config_file\n", 2); while () { $config .= $_; } close (CONFIG); ($logfile) = get_tag_values ("logfile", $config); ($timeout) = get_tag_values ("singletesttimeout", $config); ($display_errors) = get_tag_values("displayerrors", $config); ($display_warnings) = get_tag_values ("displaywarnings", $config); ($numthreads) = get_tag_values ("numthreads", $config); ($env_set_threads_command) = get_tag_values("envsetthreadscommand",$config); $env_set_threads_command =~ s/\%n/$numthreads/g; @languages = get_tag_values ("language", $config); if (!defined($opt_compile)) {$opt_compile = 1;} if (!defined($opt_run)) {$opt_run = 1;} if (!defined($opt_orphan)) {$opt_orphan = 1;} if (!defined($opt_resultsfile)) {($opt_resultsfile) = get_tag_values("resultsfile", $config);} if ( defined($opt_numthreads) && ($opt_numthreads > 0)) {$numthreads = $opt_numthreads;} if ($debug_mode) { print <) { if (/^\s*#/) {next TEST;} if (/^\s*$/) {next TEST;} $opt_test = $_; chomp ($opt_test); execute_single_test (); } # print Dumper(@test_results); } # Function that executes a system command but takes care of the global timeout # If command did not finish inbetween returns '-' otherwise the exit status of # the system command sub timed_sys_command { my ($command) = @_; my $exit_status = '-'; # set up the timeout for the command eval { local $SIG{ALRM} = sub {die "alarm\n"}; alarm $timeout; log_message_add ("Starting command \"$command\""); $exit_status = system ($command); alarm 0; }; # check if command finished during the maximum execution time if ($@ eq "alarm\n") { # test timed out # my $pid = Unix::PID->new(); # $pid->get_pidof($command, 1); # $pid->kill(); if ($debug_mode) { log_message_add ("Command \"$command\" reached max execution time.\n"); } return "TO"; } # test finished return $exit_status; } # Function that runs the tests given as a array containing the testnames # Returns an array containing the percent values of the passed tests and the # successful crosstests. sub run_test { my ($testname, $orphan) = @_; my $bin_name, $cbin_name; my $cmd, $exit_status, $failed; my $resulttest, $resultctest; # path to test and crosstest either in normal or in orphaned version if ($orphan) { $bin_name = "bin/$opt_lang/orph_test_$testname"; $cbin_name = "bin/$opt_lang/orph_ctest_$testname"; } else { $bin_name = "bin/$opt_lang/test_$testname"; $cbin_name = "bin/$opt_lang/ctest_$testname"; } # Check if executables exist if (! -e $bin_name) { test_error ("Could not find executable \"$bin_name\"."); return ('test' => '-', 'crosstest' => '-'); } # run the test $cmd = "$env_set_threads_command ./$bin_name >$bin_name.out"; print "Running test with $numthreads threads ."; $exit_status = timed_sys_command ($cmd); ############################################################ # Check if test finished within max execution time if ($exit_status eq 'TO') { print ".... failed (timeout)\n"; return ('test' => 'TO', 'crosstest' => '-') } ############################################################ # check if all tests were successful $failed = $exit_status >> 8; if ($failed < 0 or $failed > 100) { $failed = 100; } $resulttest = 100 - $failed; if ($resulttest eq 100) { print ".... success ..."; } else { print ".... failed $failed\% of the tests\n"; return ('test' => $resulttest, 'crosstest' => '-'); } ############################################################ # do crosstest # check if executable exist if (! -e $cbin_name) { test_error ("Could not find executable \"$cbin_name\"."); print "... not verified (crosstest missing)\n"; return ('test' => $resulttest, 'crosstest' => '-'); } # run crosstest # Test was successful, so it makes sense to run the crosstest $cmd = "$env_set_threads_command ./$cbin_name > $cbin_name.out"; $exit_status = timed_sys_command ($cmd); ############################################################ # Check if crosstest finished within max execution time if ($exit_status eq 'TO') { print "... not verified (timeout)\n"; return ('test' => $result, 'crosstest' => 'TO'); } ############################################################ # test if crosstests failed as expected $resultctest = $exit_status >> 8; if ($resultctest > 0) { print "... and verified with $resultctest\% certainty\n"; } else { print "... but might be lucky\n"; } return ('test' => $resulttest, 'crosstest' => $resultctest); ############################################################ } # Function that generates the test binaries out of the sourcecode sub compile_src { my ($testname, $orphan) = @_; print "Compiling soures ............"; if ($orphan) { # Make orphaned tests $exec_name = "bin/$opt_lang/orph_test_$testname"; $crossexe_name = "bin/$opt_lang/orph_ctest_$testname"; $resulttest = system ("make $exec_name > $exec_name\_compile.log" ); $resultctest = system ("make $crossexe_name > $crossexe_name\_compile.log" ); } else { # Make test $exec_name = "bin/$opt_lang/test_$testname"; $crossexe_name = "bin/$opt_lang/ctest_$testname"; $resulttest = system ("make $exec_name > $exec_name\_compile.log" ); $resultctest = system ("make $crossexe_name > $crossexe_name\_compile.log" ); } if ($resulttest) { test_error ("Compilation of the test failed."); } if ($resultctest){ test_error ("Compilation of the crosstest failed."); } if ($resulttest or $resultctest) { print ".... failed\n"; return 0; } else { print ".... success\n"; return 1; } } # Function which prepare the directory structure: sub init_directory_structure { my ($language) = @_; if (-e "bin" && -d "bin") { warning ("Old binary directory detected!");} else { system ("mkdir bin"); } if (-e "bin/$language" && -d "bin/$language") { warning ("Old binary directory for language $language found.");} else { system ("mkdir bin/$language"); } } # Function that generates the sourcecode for the given test sub make_src { my ($testname, $orphan) = @_; my $template_file; my $src_name; $template_file = "$dir/$testname.$extension"; if (!-e $template_file) { test_error ("Could not find template for \"$testname\""); } print "Generating sources .........."; if ($orphan) { # Make orphaned tests $src_name = "bin/$opt_lang/orph_test_$testname.$extension"; $resulttest = system ("./$templateparsername --test --orphan $template_file $src_name"); $src_name = "bin/$opt_lang/orph_ctest_$testname.$extension"; $resultctest = system ("./$templateparsername --crosstest --orphan $template_file $src_name"); } else { # Make test $src_name = "bin/$opt_lang/test_$testname.$extension"; $resulttest = system ("./$templateparsername --test --noorphan $template_file $src_name"); $src_name = "bin/$opt_lang/ctest_$testname.$extension"; $resultctest = system ("./$templateparsername --crosstest --noorphan $template_file $src_name"); } if ($resulttest) { test_error ("Generation of sourcecode for the test failed."); } if ($resultctest){ test_error ("Generation of sourcecode for the crosstest failed."); } if ($resulttest or $resultctest) { print ".... failed\n"; return 0; } else { print ".... success\n"; return 1; } } # Function which checks if a given test is orphanable sub test_is_orphanable { my ($testname) = @_; my $src; my $file = "$dir/$testname.$extension"; if(! -e $file){ test_error ("Could not find test file $file\n");} open (TEST, "<$file") or test_error ("Could not open test file $file\n"); while () { $src .= $_; } close (TEST); return $src =~/ompts:orphan/; } sub write_result_file_head { open (RESULTS, ">$opt_resultsfile") or error ("Could not open file '$opt_resultsfile' to write results.", 1); $resultline = sprintf "%-25s %-s\n", "#Tested Directive", "\tt\tct\tot\toct"; print RESULTS $resultline; } # Function which adds a result to the list of results sub add_result { my ($testname, $result) = @_; # print Dumper(@{$result}); $num_constructs++; open (RESULTS, ">>$opt_resultsfile") or error ("Could not open file '$opt_resultsfile' to write results.", 1); if (${$result}[0][0]) { $num_tests ++;} if ($opt_compile and ${$result}[0][1] eq 0) { ${$result}[0][2]{test} = 'ce'; ${$result}[0][2]{crosstest} = '-'; $num_normal_tests_compile_error++; $num_normal_tests_failed++; } if ($opt_run and ${$result}[0][2] and ${$result}[0][2]{test} ne 'ce') { if (${$result}[0][2]{test} == 100) { $num_normal_tests_successful++; if (${$result}[0][2]{crosstest} == 100){ $num_normal_tests_verified++;} } elsif (${$result}[0][2]{test} eq 'TO'){ $num_normal_tests_timed_out++; $num_normal_tests_failed++; } else { $num_normal_tests_failed++; } } $resultline = "${$result}[0][2]{test}\t${$result}[0][2]{crosstest}\t"; if (${$result}[1][0]) { $num_tests ++;} else { $resultline .= "-\t-\n"; } if ($opt_compile and ${$result}[1][1] eq 0) { ${$result}[1][2]{test} = 'ce'; ${$result}[1][2]{crosstest} = '-'; $num_orphaned_tests_compile_error++; $num_orphaned_tests_failed++; } if ($opt_run and ${$result}[1][2] and ${$result}[1][2]{test} ne 'ce') { if (${$result}[1][2]{test} == 100) { $num_orphaned_tests_successful++; if (${$result}[1][2]{crosstest} == 100){ $num_orphaned_tests_verified++;} } elsif (${$result}[1][2]{test} eq 'TO'){ $num_orphaned_tests_timed_out++; $num_orphaned_tests_failed++; } else { $num_orphaned_tests_failed++; } } $resultline .= "${$result}[1][2]{test}\t${$result}[1][2]{crosstest}\n"; $num_failed_tests = $num_normal_tests_failed + $num_orphaned_tests_failed; $num_failed_compilation = $num_normal_tests_compile_error + $num_orphaned_tests_compile_error; $num_successful_tests = $num_normal_tests_successful + $num_orphaned_tests_successful; $num_verified_tests = $num_normal_tests_verified + $num_orphaned_tests_verified; $resultline2 = sprintf "%-25s %-s", "$testname", "\t$resultline"; print RESULTS $resultline2; } # Function which executes a single test sub execute_single_test { my @result; init_language_settings ($opt_lang); init_directory_structure ($opt_lang); log_message_add ("Testing for \"$opt_test\":"); print "Testing for \"$opt_test\":\n"; # tests in normal mode if ($opt_compile){ $result[0][0] = make_src ($opt_test, 0); $result[0][1] = compile_src ($opt_test, 0);} if ($opt_run && $result[0][1] == 1) { $result[0][2] = {run_test ($opt_test, 0)};} # tests in orphaned mode if ($opt_orphan && test_is_orphanable($opt_test)){ log_message_add ("Testing for \"$opt_test\" in orphaned mode:"); print "+ orphaned mode:\n"; if ($opt_compile) { $result[1][0] = make_src ($opt_test, 1); $result[1][1] = compile_src ($opt_test, 1);} if ($opt_run && $result[1][1] == 1) { $result[1][2] = {run_test ($opt_test, 1)};} } add_result($opt_test, \@result); } # Function that prints info about a given test sub print_testinfo { init_language_settings($opt_lang); my $doc = ""; my $file = $dir."/".$opt_testinfo.".".$extension; if (! -e $file) {error ("Could not find template for test $opt_testinfo", 5);} open (TEST,"<$file") or error ("Could not open template file \"$file\" for test $opt_testinfo", 6); while () {$doc .= $_;} close (TEST); (my $omp_version) = get_tag_values ("ompts:ompversion", $doc); (my $dependences) = get_tag_values ("ompts:dependences", $doc); (my $description) = get_tag_values ("ompts:testdescription", $doc); my $orphanable = 'no'; if ($doc =~ /ompts:orphan/) {$orphanable = 'yes';} print < 0) { print "Available languages:\n"; foreach (@languages) { (my $name) = get_tag_values ("languagename", $_); print "$name\n"; } } else { print "No languages available\n"; } } # Function that prints the error message sub print_help_text { print <>$logfile") or die "ERROR: Could not create $logfile\n"; print LOGFILE "$mday/$mon/$year $hour.$min.$sec: $message\n"; }