Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
[simgrid.git] / buildtools / Cmake / tesh.pl
1 #! /usr/bin/perl -w
2
3 =encoding UTF-8
4
5 =head1 NAME
6
7 tesh -- testing shell
8
9 =head1 SYNOPSIS
10
11 B<tesh> [I<options>] I<tesh_file>
12
13 =cut
14
15 use Pod::Usage qw(pod2usage);
16 use Getopt::Long qw(GetOptions);
17 use strict;
18 use Term::ANSIColor;
19 use IPC::Open3;
20
21
22 my($line1,$line2,$execline,$command,$command_tesh);
23 my($command_executed)=0;
24 my($expected_result_line)=0;
25 my($sort)=0;
26 my($nb_arg)=0;
27 my(@list1,@list2,@list3,@list_of_commands)=();
28 my(@buffer)=();
29 my($timeout)=0;
30 my($encore)=0;
31 my($old_buffer);
32 my($linebis);
33 my($SIGABRT)=0;
34 my($no_output_ignore)=1;
35 my($verbose)=0;
36 my($return)=-1;
37 my($pid);
38 my($result);
39 my($result_err);
40 my($fich_name);
41 my($forked);
42 my($config)="";
43
44 my($tesh_command)=0;
45 my(@buffer_tesh)=();
46
47 # make sure we received a tesh file
48 scalar @ARGV > 0 || pod2usage(-exitval => 1);
49
50 #Add current directory to path
51 $ENV{PATH} = "$ENV{PATH}:.";
52
53
54 #options
55 sub cd_cmd {
56     my $directory=$_[1];
57     if (-e $directory) {
58         chdir("$directory");
59         print "[Tesh/INFO] change directory to $directory\n";
60     } else {
61         die "[Tesh/CRITICAL] Directory not found : \"$directory\"\n";
62     }
63 }
64
65 sub setenv_cmd {
66     if ($_[1] =~ /^(.*)=(.*)$/) {
67         my($var,$ctn)=($1,$2);
68         $ENV{$var} = $ctn;
69         print "[Tesh/INFO] setenv $var=$ctn\n";
70     } else { 
71         die "[Tesh/CRITICAL] Malformed argument to setenv: expected 'name=value' but got '$_[1]'\n";
72     }
73 }
74
75 my $tesh_file;
76 sub get_options {
77     # remove the tesh file from the ARGV used
78     my @ARGV = @_;
79     $tesh_file = pop @ARGV;
80
81     # temporary arrays for GetOption
82     my @verbose = ();
83     my @cfg;
84
85     my %opt = (
86         "help"    => 0,
87         "debug"   => 0,
88         "verbose" => 0
89         );
90
91     Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev');
92     
93     GetOptions(
94         'help|h'     => \$opt{'help'},
95
96         'verbose|v'  => \@verbose,
97         'debug|d'    => \$opt{"debug"},
98
99         'cd=s'       => \&cd_cmd,
100         'setenv=s'   => \&setenv_cmd,
101         'cfg=s'      => \@cfg,
102         );
103
104     $opt{'verbose'} = scalar @verbose;
105     foreach (@cfg) {
106         $opt{'cfg'} .= " --cfg=$_";
107     }
108     return %opt;
109 }
110
111 my %opts = get_options(@ARGV);
112
113 # parse tesh file
114 open SH_LIGNE, $tesh_file or die "[Tesh/CRITICAL] Unable to open $tesh_file: $!\n";
115
116 while(defined($line1=<SH_LIGNE>))
117 {
118         if($line1 =~ /^\< \$ /){        # arg command line
119                 $line1 =~ s/\${EXEEXT:=}//g;
120                 $line1 =~ s/^\< \$\ *//g;
121                 $line1 =~ s/^.\/lua/lua/g;
122                 $line1 =~ s/^.\/ruby/ruby/g;
123                 $line1 =~ s/^.\///g;
124                 $line1 =~ s/^tesh/.\/tesh/g;
125                 $line1 =~ s/\(%i:%P@%h\)/\\\(%i:%P@%h\\\)/g;
126                 chomp $line1;
127                 $command_tesh = $line1;
128                 print "[Tesh/INFO] arg_exec_line   : $command_tesh\n";
129         }
130         elsif($line1 =~ /^\< \< /){  # arg buffer line
131                 $line1 =~ s/^\< \<\ *//g;
132                 chomp $line1;
133                 print "[Tesh/INFO] arg_buffer_line : $line1\n";
134                 push @buffer_tesh, "$line1\n";
135         }
136         elsif($line1 =~ /^\< \> /){  # arg output line
137                 $line1 =~ s/^\< \>\ *//g;
138                 $line1 =~ s/\r//g;
139                 chomp $line1;
140                 push @list2, $line1;
141                 print "[Tesh/INFO] arg_output_line : $line1\n";
142                 $expected_result_line = 1;
143         }
144         elsif($line1 =~ /^\$ mkfile/){          # "mkfile" command line
145                 $line1 =~ s/\$ //g;
146                 $line1 =~ s/mkfile//g;
147                 chomp $line1;
148                 $fich_name = $line1;
149                 $line1 =();
150                 print "[Tesh/INFO] exec_line : mkfile $fich_name\n";
151                 `rm -f $fich_name`;
152                 open(FILE,">$fich_name") or die "[Tesh/CRITICAL] Unable to make file : $fich_name. $!\n";
153                 print FILE @buffer;
154                 close(FILE);
155                 @buffer = ();   
156         }
157         elsif($line1 =~ /^\$ cd/){      # "cd" command line
158                 $line1 =~ s/\$ //g;
159                 chomp $line1;
160                 print "[Tesh/INFO] exec_line : $line1\n";
161                 $line1 =~ s/cd //g;
162                 chdir("$line1") or die "[Tesh/CRITICAL] Unable to open $line1. $!\n";   
163         }
164         elsif($line1 =~ /^\$ /){        #command line
165                 if($line1 =~ /^\$ .\/tesh/){    # tesh command line
166                         $tesh_command = 1;
167                         @buffer = @buffer_tesh;
168                         @buffer_tesh=();
169                 }
170                 $line1 =~ s/\${EXEEXT:=}//g;
171                 $line1 =~ s/^\$\ *//g;
172                 $line1 =~ s/^.\/lua/lua/g;
173                 $line1 =~ s/^.\/ruby/ruby/g;
174                 $line1 =~ s/^.\///g;
175                 $line1 =~ s/^tesh/.\/tesh/g;
176                 $line1 =~ s/\(%i:%P@%h\)/\\\(%i:%P@%h\\\)/g;
177                 chomp $line1;
178                 $line1 = "$line1 $config";
179                 
180                 if(@list1){
181                         print color("red");
182                         print "[Tesh/CRITICAL] -\n";
183                         print "[Tesh/CRITICAL] + @list1";
184                         print color("reset"), "\n";
185                         die;}           
186                 if(@list_of_commands){ # need parallel execution
187                         push @list_of_commands, $line1;
188                         print "[Tesh/INFO] exec_line : $line1\n";
189                 }
190                 else{
191                         print "[Tesh/INFO] exec_line : $line1\n";
192                         if($tesh_command)
193                         {       $execline = $command_tesh;
194                                 $tesh_command=0;}
195                         else
196                         {       $execline = $line1;}
197                         $pid = open3(\*IN, \*OUT, \*OUT, $execline );
198                         if( $timeout){
199                                 $forked = fork();die "fork() failed: $!" unless defined $forked;
200                                 if ( $forked == 0 )
201                                 {
202                                 sleep $timeout;
203                                 kill(9, $pid);
204                                 exit;
205                                 }
206                         }
207                         
208                         while(@buffer)
209                         {
210                                 $line1 = shift (@buffer);
211                                 print IN $line1;
212                         }
213                         close IN ;
214                         
215                         waitpid( $pid, 0 );
216                         if($timeout){kill(9, $forked);$timeout=0;}
217                         $timeout = 0;
218                         
219                         while(defined($linebis=<OUT>))
220                         {
221                                 $linebis =~ s/\r//g;
222                                 $linebis =~ s/^( )*//g;
223                                 chomp $linebis;
224                                 push @list1,"$linebis";
225                         }       
226                         close OUT;
227                         $command_executed = 1;
228                 }
229         }
230         elsif($line1 =~ /^\& /){        # parallel command line
231                 $command_executed = 0;
232                 $expected_result_line = 0;
233                 $line1 =~ s/\${EXEEXT:=}//g;
234                 $line1 =~ s/^\& //g;
235                 $line1 =~ s/^.\/lua/lua/g;
236                 $line1 =~ s/^.\/ruby/ruby/g;
237                 $line1 =~ s/^.\///g;
238                 $line1 =~ s/\(%i:%P@%h\)/\\\(%i:%P@%h\\\)/g;
239                 chomp $line1;
240                 $line1 = "$line1 $config";
241                 
242                 $execline = "$line1";
243                 print "[Tesh/INFO] exec_line : $execline\n";
244                 push @list_of_commands, $execline;      
245         }       
246         elsif($line1 =~ /^\>/){ #expected result line
247                 $line1 =~ s/^\>( )*//g;
248                 $line1 =~ s/\r//g;
249                 chomp $line1;
250                 push @list2, $line1;
251                 $expected_result_line = 1;
252         }
253         elsif($line1 =~ /^\</ or $encore==1){   #need to buffer
254                 $line1 =~ s/^\<( )*//g; #delete < with space or tab after
255                 $line1 =~ s/\r//g;
256                 chomp $line1;
257                 if($line1 =~ /\\$/) # need to store this line into old_buff
258                 {
259                         $encore=1;
260                         $line1 =~ s/\\$//g;
261                         $old_buffer = "$old_buffer$line1";
262                 }
263                 else
264                 {
265                         if($encore == 1){push @buffer, "$old_buffer$line1";}
266                         else{push @buffer, "$line1\n";}
267                         $old_buffer = ();
268                         $encore = 0;    
269                 }
270         }
271         elsif($line1 =~ /^p/){  #comment
272                 $line1 =~ s/^p //g;
273                 $line1 =~ s/\r//g;
274                 chomp $line1;
275                 print "[Tesh/INFO] comment_line :$line1\n";
276         }
277         elsif($line1 =~ /^! output sort/){      #output sort
278                 $sort=1;
279         }
280         elsif($line1 =~ /^! output ignore/){    #output ignore
281                 $no_output_ignore=0;
282         }
283         elsif($line1 =~ /^! expect signal SIGABRT$/) #expect signal SIGABRT
284         {
285                 $SIGABRT=1;
286         }
287         elsif($line1 =~ /^! expect return/){    #expect return
288                 $line1 =~ s/^! expect return //g;
289                 $line1 =~ s/\r//g;
290                 chomp $line1;
291                 $return = $line1;
292                 print color("red"), "[Tesh/INFO] expect return $return";
293                 print color("reset"), "\n";
294                 die;
295         }
296         elsif($line1 =~ /^! setenv/){   #setenv
297                 $line1 =~ s/^! setenv //g;
298                 $line1 =~ s/\r//g;
299                 chomp $line1;
300                 $line1 =~ /^(.*)=(.*)$/;
301                 $ENV{$1} = $2;
302                 print "[Tesh/INFO] setenv: $1=$2\n";
303         }
304         elsif($line1 =~ /^! include/){  #output sort
305                 print color("red"), "[Tesh/CRITICAL] need include";
306                 print color("reset"), "\n";
307                 die;
308         }
309         elsif($line1 =~ /^! timeout/){  #timeout
310                 $line1 =~ s/^! timeout //g;
311                 $line1 =~ s/\r//g;
312                 chomp $line1;
313                 if($timeout != $line1){
314                 $timeout = $line1;
315                 print "[Tesh/INFO] timeout   : $timeout\n";}
316         }
317         elsif($line1 =~ /^! need execute/){     #need execute // commands
318                 $execline = ();
319                 $sort = 1; # need sort output
320                 while(@list_of_commands)
321                 {
322                         $command = shift (@list_of_commands);
323                         if($execline){$execline = "$command & $execline";}
324                         else{$execline = "$command";}
325                 }
326                 $pid = open3(\*IN, \*OUT, \*OUT, $execline);
327                 if( $timeout){
328                         $forked = fork();die "fork() failed: $!" unless defined $forked;
329                         if ( $forked == 0 )
330                         {
331                         sleep $timeout;
332                         kill(9, $pid);
333                         exit;
334                         }
335                 }
336                 
337                 while(@buffer)
338                 {
339                         $line1 = shift (@buffer);
340                         print IN $line1;
341                 }
342                 close IN ;
343                 waitpid( $pid, 0 );
344                 if($timeout){kill(9, $forked);$timeout=0;}
345                 $timeout = 0;
346
347                 @list1=();
348                 while(defined($linebis=<OUT>))
349                 {
350                         $linebis =~ s/\r//g;
351                         $linebis =~ s/^( )*//g;
352                         chomp $linebis;
353                         push @list1,"$linebis";
354                 }       
355                 close OUT;
356                 $command_executed = 1;
357         }
358         elsif($command_executed and $expected_result_line)
359         {
360                 if($no_output_ignore){
361                 @buffer = ();
362                 if($sort == 1)
363                 {
364                         @list3 = sort @list1;
365                         @list1=();
366                         @list1=@list3;
367                         @list3=();
368                         
369                         @list3 = sort @list2;
370                         @list2=();
371                         @list2=@list3;
372                         @list3=();
373                         
374                         $sort=0;
375                 }
376                 if($SIGABRT)
377                 {
378                         push @list2,"Aborted";
379                         $SIGABRT = 0;
380                 }
381                                 
382                 while(@list1 or @list2)
383                 {
384                         if(@list1){$line1 = shift (@list1);$expected_result_line = "x$line1";}
385                         if(@list2){$line2 = shift (@list2);$command_executed = "x$line2";}
386                         if($command_executed and $expected_result_line)
387                         {
388                                 
389                                 if($line1 eq $line2){
390                                         if($verbose == 1){print color("green"),"[Tesh/VERB] $line1\n",color("reset");}
391                                         else{push @buffer, "[Tesh/CRITICAL]   $line1\n";}
392                                         
393                                 }
394                                 else
395                                 {       if($verbose == 0){print color("green"),@buffer,color("reset");}
396                                         if($line2) {print color("red"), "[Tesh/CRITICAL] - $line2",color("reset"),"\n";}
397                                         if($line1) {print color("red"), "[Tesh/CRITICAL] + $line1",color("reset"),"\n";}
398                                         die;
399                                 }
400                         }
401                         else
402                         {       if($verbose == 0){print color("green"),@buffer,color("reset");}
403                                 if($line2) {print color("red"), "[Tesh/CRITICAL] - $line2",color("reset"),"\n";}
404                                 if($line1) {print color("red"), "[Tesh/CRITICAL] + $line1",color("reset"),"\n";}
405                                 die;
406                         }
407                 }
408                 }else{$no_output_ignore = 1;}
409                 $command_executed = 0;
410                 $expected_result_line = 0;
411                 @list1=();
412                 @list2=();
413                 @buffer = ();
414                 $tesh_command=0;
415                 @buffer_tesh=();
416         }
417
418 }
419
420 if(@list_of_commands){ # need parallel execution
421         $execline = ();
422         $sort = 1; # need sort output
423         while(@list_of_commands)
424         {
425                 $command = shift (@list_of_commands);
426                 if($execline){$execline = "$command & $execline";}
427                 else{$execline = "$command";}
428         }
429         print "[Tesh/INFO] exec_line : $execline\n";
430         $pid = open3(\*IN, \*OUT, \*OUT,"$execline");
431
432         if( $timeout){
433                 $forked = fork();die "fork() failed: $!" unless defined $forked;
434                 if ( $forked == 0 )
435                 {
436                 sleep $timeout;
437                 kill(9, $pid);
438                 exit;
439                 }
440         }
441         
442         while(@buffer)
443         {
444                 $line1 = shift (@buffer);
445                 print IN $line1;
446         }
447         close IN ;
448         waitpid( $pid, 0 );
449         if($timeout){kill(9, $forked);$timeout=0;}
450         $timeout = 0;
451
452         @list1=();
453         while(defined($linebis=<OUT>))
454         {
455                 $linebis =~ s/\r//g;
456                 $linebis =~ s/^( )*//g;
457                 chomp $linebis;
458                 push @list1,"$linebis";
459         }       
460         close OUT;
461         $command_executed = 1;
462 }
463
464 if($command_executed and $expected_result_line ){
465                         if($no_output_ignore){
466                         @buffer = ();
467                         if($sort == 1)
468                         {
469                                 @list3 = sort @list1;
470                                 @list1=();
471                                 @list1=@list3;
472                                 @list3=();
473                                 
474                                 @list3 = sort @list2;
475                                 @list2=();
476                                 @list2=@list3;
477                                 @list3=();
478                                 
479                                 $sort=0;
480                         }
481                         if($SIGABRT)
482                         {
483                                 push @list2,"Aborted";
484                                 $SIGABRT = 0;
485                         }
486                         
487                         while(@list1 or @list2)
488                         {
489                                 if(@list1){$line1 = shift (@list1);$expected_result_line = "x$line1";}
490                                 if(@list2){$line2 = shift (@list2);$command_executed = "x$line2";}
491                                 if($command_executed and $expected_result_line)
492                                 {
493                                         if($line1 eq $line2){
494                                                 if($verbose == 1){print color("green"),"[Tesh/VERB] $line1\n",color("reset");}
495                                                 else{push @buffer, "[Tesh/CRITICAL]   $line1\n";}
496                                                 
497                                         }
498                                         else
499                                         {       if($verbose == 0){print color("green"),@buffer,color("reset");}
500                                                 if($line2) {print color("red"), "[Tesh/CRITICAL] - $line2",color("reset"),"\n";}
501                                                 if($line1) {print color("red"), "[Tesh/CRITICAL] + $line1",color("reset"),"\n";}
502                                                 die;
503                                         }
504                                 }
505                                 else
506                                 {       if($verbose == 0){print color("green"),@buffer,color("reset");}
507                                         if($line2) {print color("red"), "[Tesh/CRITICAL] - $line2",color("reset"),"\n";}
508                                         if($line1) {print color("red"), "[Tesh/CRITICAL] + $line1",color("reset"),"\n";}
509                                         die;
510                                 }
511                         }
512                         }else{$no_output_ignore = 1;}
513                         $command_executed = 0;
514                         $expected_result_line= 0;
515                         @list1=();
516                         @list2=();
517                         @buffer = ();
518 }