blob: 3472351a9ef614c89d9228d939bee4841c97a28e [file] [log] [blame]
Jim Cownie18d84732014-05-10 17:02:09 +00001#!/usr/bin/env perl
2
3# runtest [options] FILENAME
4#
5# Read the file FILENAME. Each line contains a test.
6# Convert template to test and crosstest.
7# If possilble generate orphaned testversions, too.
8# Use make to compile the test
9
10################################################################################
11# Global configuration options for the runtestscript itself:
12################################################################################
13
14# name of the global configuration file for the testsuite:
15$config_file = "ompts.conf";
16$logfile = "ompts.log"; # overwriteable by value in config file
17$env_set_threads_command = 'OMP_NUM_THREADS=%n; export OMP_NUM_THREADS;';
18$debug_mode = 0;
19################################################################################
20# After this line the script part begins! Do not edit anithing below
21################################################################################
22
23
24# Namespaces:
25use Getopt::Long;
26#use Unix::PID;
27use Data::Dumper;
28use ompts_parserFunctions;
29
30# Extracting given options
31GetOptions("help",
32 "listlanguages",
33 "lang=s",
34 "list",
35 "testinfo=s",
36 "numthreads=i",
37 "test=s",
38 "compile!",
39 "run!",
40 "orphan!",
41 "resultfile=s"
42 );
43
44# Get global configuratino options from config file:
45if(! -e $config_file){ error ("Could not find config file $config_file\n", 1);}
46open (CONFIG, "<$config_file") or error ("Could not open config file $config_file\n", 2);
47while (<CONFIG>) { $config .= $_; }
48close (CONFIG);
49
50($logfile) = get_tag_values ("logfile", $config);
51($timeout) = get_tag_values ("singletesttimeout", $config);
52($display_errors) = get_tag_values("displayerrors", $config);
53($display_warnings) = get_tag_values ("displaywarnings", $config);
54($numthreads) = get_tag_values ("numthreads", $config);
55($env_set_threads_command) = get_tag_values("envsetthreadscommand",$config);
56$env_set_threads_command =~ s/\%n/$numthreads/g;
57@languages = get_tag_values ("language", $config);
58
59if (!defined($opt_compile)) {$opt_compile = 1;}
60if (!defined($opt_run)) {$opt_run = 1;}
61if (!defined($opt_orphan)) {$opt_orphan = 1;}
62if (!defined($opt_resultsfile)) {($opt_resultsfile) = get_tag_values("resultsfile", $config);}
63if ( defined($opt_numthreads) && ($opt_numthreads > 0)) {$numthreads = $opt_numthreads;}
64if ($debug_mode) {
65print <<EOF;
66Testsuite configuration:
67Logfile = $logfile
68Timeout = $timeout seconds
69Language: $opt_lang
70Display errors: $display_errors
71Display warnings: $display_warnings
72Resultsfile: $opt_resultsfile
73Numthreads: $numthreads
74------------------------------
75EOF
76}
77
78$num_construcs = 0;
79$num_tests = 0;
80$num_failed_tests = 0;
81$num_successful_tests = 0;
82$num_verified_tests = 0;
83$num_failed_compilation = 0;
84
85$num_normal_tests_failed = 0;
86$num_normal_tests_compile_error = 0;
87$num_normal_tests_timed_out = 0;
88$num_normal_tests_successful = 0;
89$num_normal_tests_verified = 0;
90
91$num_orphaned_tests_failed = 0;
92$num_orphaned_tests_compile_error = 0;
93$num_orphaned_tests_timed_out = 0;
94$num_orphaned_tests_successful = 0;
95$num_orphaned_tests_verified = 0;
96
97if ($opt_help) { print_help_text (); exit 0; }
98if ($opt_listlanguages){ print_avail_langs (); exit 0; }
99if ($opt_list) { print_avail_tests (); exit 0; }
100if ($opt_testinfo) { print_testinfo (); exit 0; }
101if ($opt_test) { write_result_file_head();
102 execute_single_test (); exit 0; }
103if (-e $ARGV[0]) { write_result_file_head();
104 execute_testlist($ARGV[0]); print_results();
105 result_summary(); exit 0;}
106
107################################################################################
108# sub function definitions
109################################################################################
110
111# Function which prints the results file
112sub print_results
113{
114 system("echo; cat $opt_resultsfile; echo;");
115}
116
117# Function which prints a summary of all test
118sub result_summary
119{
120 my $num_directives = @test_results;
121
122 print <<EOF;
123
124Summary:
125S Number of tested Open MP constructs: $num_constructs
126S Number of used tests: $num_tests
127S Number of failed tests: $num_failed_tests
128S Number of successful tests: $num_successful_tests
129S + from this were verified: $num_verified_tests
130
131Normal tests:
132N Number of failed tests: $num_normal_tests_failed
133N + from this fail compilation: $num_normal_tests_compile_error
134N + from this timed out $num_normal_tests_timed_out
135N Number of successful tests: $num_normal_tests_successful
136N + from this were verified: $num_normal_tests_verified
137
138Orphaned tests:
139O Number of failed tests: $num_orphaned_tests_failed
140O + from this fail compilation: $num_orphaned_tests_compile_error
141O + from this timed out $num_orphaned_tests_timed_out
142O Number of successful tests: $num_orphaned_tests_successful
143O + from this were verified: $num_orphaned_tests_verified
144EOF
145
146}
147
148# Function that executest the tests specified in the given list
149sub execute_testlist
150{
151 my ($filename) = @_;
152 # opening testlist
153 open(TESTS,$filename) or error ("Could not open $filename\n", 1);
154TEST: while (<TESTS>) {
155 if (/^\s*#/) {next TEST;}
156 if (/^\s*$/) {next TEST;}
157 $opt_test = $_;
158 chomp ($opt_test);
159 execute_single_test ();
160 }
161# print Dumper(@test_results);
162}
163
164# Function that executes a system command but takes care of the global timeout
165# If command did not finish inbetween returns '-' otherwise the exit status of
166# the system command
167sub timed_sys_command
168{
169 my ($command) = @_;
170 my $exit_status = '-';
171
172# set up the timeout for the command
173 eval {
174 local $SIG{ALRM} = sub {die "alarm\n"};
175 alarm $timeout;
176 log_message_add ("Starting command \"$command\"");
177 $exit_status = system ($command);
178 alarm 0;
179 };
180# check if command finished during the maximum execution time
181 if ($@ eq "alarm\n") {
182# test timed out
183# my $pid = Unix::PID->new();
184# $pid->get_pidof($command, 1);
185# $pid->kill();
186 if ($debug_mode) {
187 log_message_add ("Command \"$command\" reached max execution time.\n");
188 }
189 return "TO";
190 }
191# test finished
192 return $exit_status;
193}
194
195# Function that runs the tests given as a array containing the testnames
196# Returns an array containing the percent values of the passed tests and the
197# successful crosstests.
198sub run_test
199{
200 my ($testname, $orphan) = @_;
201 my $bin_name, $cbin_name;
202 my $cmd, $exit_status, $failed;
203 my $resulttest, $resultctest;
204
205# path to test and crosstest either in normal or in orphaned version
206 if ($orphan) {
207 $bin_name = "bin/$opt_lang/orph_test_$testname";
208 $cbin_name = "bin/$opt_lang/orph_ctest_$testname";
209 } else {
210 $bin_name = "bin/$opt_lang/test_$testname";
211 $cbin_name = "bin/$opt_lang/ctest_$testname";
212 }
213# Check if executables exist
214 if (! -e $bin_name) {
215 test_error ("Could not find executable \"$bin_name\".");
216 return ('test' => '-', 'crosstest' => '-');
217 }
218# run the test
219 $cmd = "$env_set_threads_command ./$bin_name >$bin_name.out";
220 print "Running test with $numthreads threads .";
221 $exit_status = timed_sys_command ($cmd);
222############################################################
223# Check if test finished within max execution time
224 if ($exit_status eq 'TO') {
225 print ".... failed (timeout)\n";
226 return ('test' => 'TO', 'crosstest' => '-')
227 }
228############################################################
229# check if all tests were successful
230 $failed = $exit_status >> 8;
231 if ($failed < 0 or $failed > 100) { $failed = 100; }
232 $resulttest = 100 - $failed;
233 if ($resulttest eq 100) {
234 print ".... success ...";
235 } else {
236 print ".... failed $failed\% of the tests\n";
237 return ('test' => $resulttest, 'crosstest' => '-');
238 }
239############################################################
240
241# do crosstest
242# check if executable exist
243 if (! -e $cbin_name) {
244 test_error ("Could not find executable \"$cbin_name\".");
245 print "... not verified (crosstest missing)\n";
246 return ('test' => $resulttest, 'crosstest' => '-');
247 }
248# run crosstest
249# Test was successful, so it makes sense to run the crosstest
250 $cmd = "$env_set_threads_command ./$cbin_name > $cbin_name.out";
251 $exit_status = timed_sys_command ($cmd);
252############################################################
253# Check if crosstest finished within max execution time
254 if ($exit_status eq 'TO') {
255 print "... not verified (timeout)\n";
256 return ('test' => $result, 'crosstest' => 'TO');
257 }
258############################################################
259# test if crosstests failed as expected
260 $resultctest = $exit_status >> 8;
261 if ($resultctest > 0) {
262 print "... and verified with $resultctest\% certainty\n";
263 } else {
264 print "... but might be lucky\n";
265 }
266 return ('test' => $resulttest, 'crosstest' => $resultctest);
267############################################################
268}
269
270# Function that generates the test binaries out of the sourcecode
271sub compile_src
272{
273 my ($testname, $orphan) = @_;
274 print "Compiling soures ............";
275 if ($orphan) {
276# Make orphaned tests
277 $exec_name = "bin/$opt_lang/orph_test_$testname";
278 $crossexe_name = "bin/$opt_lang/orph_ctest_$testname";
279 $resulttest = system ("make $exec_name > $exec_name\_compile.log" );
280 $resultctest = system ("make $crossexe_name > $crossexe_name\_compile.log" );
281 } else {
282# Make test
283 $exec_name = "bin/$opt_lang/test_$testname";
284 $crossexe_name = "bin/$opt_lang/ctest_$testname";
285 $resulttest = system ("make $exec_name > $exec_name\_compile.log" );
286 $resultctest = system ("make $crossexe_name > $crossexe_name\_compile.log" );
287 }
288 if ($resulttest) { test_error ("Compilation of the test failed."); }
289 if ($resultctest){ test_error ("Compilation of the crosstest failed."); }
290
291 if ($resulttest or $resultctest) {
292 print ".... failed\n";
293 return 0;
294 } else {
295 print ".... success\n";
296 return 1;
297 }
298}
299
300# Function which prepare the directory structure:
301sub init_directory_structure
302{
303 my ($language) = @_;
304 if (-e "bin" && -d "bin") { warning ("Old binary directory detected!");}
305 else { system ("mkdir bin"); }
306 if (-e "bin/$language" && -d "bin/$language") {
307 warning ("Old binary directory for language $language found.");}
308 else { system ("mkdir bin/$language"); }
309}
310
311# Function that generates the sourcecode for the given test
312sub make_src
313{
314 my ($testname, $orphan) = @_;
315 my $template_file;
316 my $src_name;
317
318 $template_file = "$dir/$testname.$extension";
319 if (!-e $template_file) { test_error ("Could not find template for \"$testname\""); }
320
321 print "Generating sources ..........";
322 if ($orphan) {
323# Make orphaned tests
324 $src_name = "bin/$opt_lang/orph_test_$testname.$extension";
325 $resulttest = system ("./$templateparsername --test --orphan $template_file $src_name");
326 $src_name = "bin/$opt_lang/orph_ctest_$testname.$extension";
327 $resultctest = system ("./$templateparsername --crosstest --orphan $template_file $src_name");
328 } else {
329# Make test
330 $src_name = "bin/$opt_lang/test_$testname.$extension";
331 $resulttest = system ("./$templateparsername --test --noorphan $template_file $src_name");
332 $src_name = "bin/$opt_lang/ctest_$testname.$extension";
333 $resultctest = system ("./$templateparsername --crosstest --noorphan $template_file $src_name");
334 }
335 if ($resulttest) { test_error ("Generation of sourcecode for the test failed."); }
336 if ($resultctest){ test_error ("Generation of sourcecode for the crosstest failed."); }
337
338 if ($resulttest or $resultctest) {
339 print ".... failed\n";
340 return 0;
341 } else {
342 print ".... success\n";
343 return 1;
344 }
345}
346
347# Function which checks if a given test is orphanable
348sub test_is_orphanable
349{
350 my ($testname) = @_;
351 my $src;
352 my $file = "$dir/$testname.$extension";
353 if(! -e $file){ test_error ("Could not find test file $file\n");}
354 open (TEST, "<$file") or test_error ("Could not open test file $file\n");
355 while (<TEST>) { $src .= $_; }
356 close (TEST);
357 return $src =~/ompts:orphan/;
358}
359
360sub write_result_file_head
361{
362 open (RESULTS, ">$opt_resultsfile") or error ("Could not open file '$opt_resultsfile' to write results.", 1);
363 $resultline = sprintf "%-25s %-s\n", "#Tested Directive", "\tt\tct\tot\toct";
364 print RESULTS $resultline;
365}
366
367# Function which adds a result to the list of results
368sub add_result
369{
370 my ($testname, $result) = @_;
371# print Dumper(@{$result});
372
373 $num_constructs++;
374
375 open (RESULTS, ">>$opt_resultsfile") or error ("Could not open file '$opt_resultsfile' to write results.", 1);
376
377 if (${$result}[0][0]) {
378 $num_tests ++;}
379
380 if ($opt_compile and ${$result}[0][1] eq 0) {
381 ${$result}[0][2]{test} = 'ce';
382 ${$result}[0][2]{crosstest} = '-';
383 $num_normal_tests_compile_error++;
384 $num_normal_tests_failed++;
385 }
386
387 if ($opt_run and ${$result}[0][2] and ${$result}[0][2]{test} ne 'ce') {
388 if (${$result}[0][2]{test} == 100) {
389 $num_normal_tests_successful++;
390 if (${$result}[0][2]{crosstest} == 100){
391 $num_normal_tests_verified++;}
392 } elsif (${$result}[0][2]{test} eq 'TO'){
393 $num_normal_tests_timed_out++;
394 $num_normal_tests_failed++;
395 } else {
396 $num_normal_tests_failed++;
397 }
398 }
399 $resultline = "${$result}[0][2]{test}\t${$result}[0][2]{crosstest}\t";
400
401 if (${$result}[1][0]) {
402 $num_tests ++;}
403 else { $resultline .= "-\t-\n"; }
404
405 if ($opt_compile and ${$result}[1][1] eq 0) {
406 ${$result}[1][2]{test} = 'ce';
407 ${$result}[1][2]{crosstest} = '-';
408 $num_orphaned_tests_compile_error++;
409 $num_orphaned_tests_failed++;
410 }
411
412 if ($opt_run and ${$result}[1][2] and ${$result}[1][2]{test} ne 'ce') {
413 if (${$result}[1][2]{test} == 100) {
414 $num_orphaned_tests_successful++;
415 if (${$result}[1][2]{crosstest} == 100){
416 $num_orphaned_tests_verified++;}
417 } elsif (${$result}[1][2]{test} eq 'TO'){
418 $num_orphaned_tests_timed_out++;
419 $num_orphaned_tests_failed++;
420 } else {
421 $num_orphaned_tests_failed++;
422 }
423 }
424 $resultline .= "${$result}[1][2]{test}\t${$result}[1][2]{crosstest}\n";
425
426 $num_failed_tests = $num_normal_tests_failed + $num_orphaned_tests_failed;
427 $num_failed_compilation = $num_normal_tests_compile_error + $num_orphaned_tests_compile_error;
428 $num_successful_tests = $num_normal_tests_successful + $num_orphaned_tests_successful;
429 $num_verified_tests = $num_normal_tests_verified + $num_orphaned_tests_verified;
430
431 $resultline2 = sprintf "%-25s %-s", "$testname", "\t$resultline";
432 print RESULTS $resultline2;
433}
434
435# Function which executes a single test
436sub execute_single_test
437{
438 my @result;
439 init_language_settings ($opt_lang);
440 init_directory_structure ($opt_lang);
441 log_message_add ("Testing for \"$opt_test\":");
442 print "Testing for \"$opt_test\":\n";
443# tests in normal mode
444 if ($opt_compile){ $result[0][0] = make_src ($opt_test, 0);
445 $result[0][1] = compile_src ($opt_test, 0);}
446 if ($opt_run && $result[0][1] == 1) {
447 $result[0][2] = {run_test ($opt_test, 0)};}
448# tests in orphaned mode
449 if ($opt_orphan && test_is_orphanable($opt_test)){
450 log_message_add ("Testing for \"$opt_test\" in orphaned mode:");
451 print "+ orphaned mode:\n";
452 if ($opt_compile) { $result[1][0] = make_src ($opt_test, 1);
453 $result[1][1] = compile_src ($opt_test, 1);}
454 if ($opt_run && $result[1][1] == 1) {
455 $result[1][2] = {run_test ($opt_test, 1)};}
456 }
457 add_result($opt_test, \@result);
458}
459
460# Function that prints info about a given test
461sub print_testinfo
462{
463 init_language_settings($opt_lang);
464 my $doc = "";
465 my $file = $dir."/".$opt_testinfo.".".$extension;
466 if (! -e $file) {error ("Could not find template for test $opt_testinfo", 5);}
467 open (TEST,"<$file") or error ("Could not open template file \"$file\" for test $opt_testinfo", 6);
468 while (<TEST>) {$doc .= $_;}
469 close (TEST);
470
471 (my $omp_version) = get_tag_values ("ompts:ompversion", $doc);
472 (my $dependences) = get_tag_values ("ompts:dependences", $doc);
473 (my $description) = get_tag_values ("ompts:testdescription", $doc);
474 my $orphanable = 'no';
475 if ($doc =~ /ompts:orphan/) {$orphanable = 'yes';}
476 print <<EOF;
477Info for test $opt_testinfo:
478Open MP standard: $omp_version
479Orphaned mode: $orphanable
480Dependencies: $dependences
481Description: $description
482EOF
483}
484
485# Function that initializes the settings for the given language
486sub init_language_settings
487{
488 my ($language) = @_;
489 foreach my $lang (@languages) {
490 (my $name) = get_tag_values ("languagename", $lang);
491 if ($name eq $language) {
492 ($extension) = get_tag_values ("fileextension", $lang);
493 ($dir) = get_tag_values ("dir", $lang);
494 ($templateparsername) = get_tag_values ("templateparsername", $lang);
495 last;
496 }
497 }
498 # Check if we found the specified language in the config file
499 if (!$extension and !$dir) {
500 error ("Language $language could not be found.\n", 3);
501 }
502}
503
504
505
506# Function that prints all available tests for the given language
507sub print_avail_tests
508{
509 init_language_settings($opt_lang);
510 my @tests;
511 opendir(DIR,"$dir") or error ("Could not open directory $dir", 4);
512 while($_ = readdir(DIR)) { if (/\.$extension$/) {s/\.$extension//; push (@tests, $_);}}
513 closedir(DIR);
514 print "Found ".(@tests)." tests:\n". "-" x 30 . "\n";
515 foreach (@tests) { print $_."\n";}
516}
517
518# Function that prints all available tests for the given language
519sub print_avail_langs
520{
521 if (@languages > 0) {
522 print "Available languages:\n";
523 foreach (@languages) {
524 (my $name) = get_tag_values ("languagename", $_);
525 print "$name\n";
526 }
527 } else {
528 print "No languages available\n";
529 }
530}
531
532# Function that prints the error message
533sub print_help_text
534{
535 print <<EOF;
536runtest.pl [options] [FILE]
537
538Executes the tests listed in FILE. FILE has to contain the names of the tests,
539one test per line. Lines starting with '#' will be ignored.
540A language has to be specified for all commands except --help and --listlanguages.
541
542Options:
543 --help displays this help message
544 --listlanguages lists all available languages
545 --lang=s select language
546 --list list available tests for a language
547 --testinfo=NAME show info for test NAME
548 --numthreads=NUM set number of threads (overwrites config file settings)
549 --test=NAME execute single test NAME
550 --nocompile do not compile tests
551 --norun do not run tests
552 --noorphan switch of orphaned tests
553 --resultfile=NAME use NAME as resultfile (overwrites config file settings)
554EOF
555}
556
557# Function that writes an error message for a failed test / part of a test
558sub test_error
559{
560 my ($message) = @_;
561 log_message_add ("ERROR: $message");
562 if ($display_errors eq 1) { print STDERR "ERROR: $message\n"; }
563}
564
565# Function that returns an warning message
566sub warning {
567 my ($message) = @_;
568 if ($display_warnings eq 1) { print "Warniong: $message\n"; }
569 log_message_add ("Warning: $message");
570}
571
572# Function that returns an error message and exits with the specified error code
573sub error {
574 my ($message, $error_code) = @_;
575 if ($display_errors eq 1) { print STDERR "ERROR: $message\n"; }
576 log_message_add ("ERROR: $message");
577 exit ($error_code);
578}
579
580# Function which adds an new entry into the logfile together with a timestamp
581sub log_message_add
582{
583 (my $message) = @_;
584 ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydat,$isdst) = localtime();
585 if(length($hour) == 1) { $hour="0$hour"; }
586 if(length($min) == 1) { $min="0$min"; }
587 if(length($sec) == 1) { $sec="0$sec"; }
588 $mon=$mon+1;
589 $year=$year+1900;
590 open (LOGFILE,">>$logfile") or die "ERROR: Could not create $logfile\n";
591 print LOGFILE "$mday/$mon/$year $hour.$min.$sec: $message\n";
592}