Home | History | Annotate | Download | only in tests
      1 #!/usr/bin/env perl
      2 # -*-perl-*-
      3 
      4 # Test driver for the Make test suite
      5 
      6 # Usage:  run_make_tests  [testname]
      7 #                         [-debug]
      8 #                         [-help]
      9 #                         [-verbose]
     10 #                         [-keep]
     11 #                         [-make <make prog>]
     12 #                        (and others)
     13 
     14 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
     15 # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
     16 # This file is part of GNU Make.
     17 #
     18 # GNU Make is free software; you can redistribute it and/or modify it under the
     19 # terms of the GNU General Public License as published by the Free Software
     20 # Foundation; either version 2, or (at your option) any later version.
     21 #
     22 # GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
     23 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     24 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     25 #
     26 # You should have received a copy of the GNU General Public License along with
     27 # GNU Make; see the file COPYING.  If not, write to the Free Software
     28 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     29 
     30 $valgrind = 0;              # invoke make with valgrind
     31 $valgrind_args = '--num-callers=15 --tool=memcheck --leak-check=full';
     32 $pure_log = undef;
     33 
     34 require "test_driver.pl";
     35 
     36 # Some target systems might not have the POSIX module...
     37 $has_POSIX = eval { require "POSIX.pm" };
     38 
     39 #$SIG{INT} = sub { print STDERR "Caught a signal!\n"; die @_; };
     40 
     41 sub valid_option
     42 {
     43    local($option) = @_;
     44 
     45    if ($option =~ /^-make([-_]?path)?$/)
     46    {
     47       $make_path = shift @argv;
     48       if (!-f $make_path)
     49       {
     50 	 print "$option $make_path: Not found.\n";
     51 	 exit 0;
     52       }
     53       return 1;
     54    }
     55 
     56    if ($option =~ /^-valgrind$/i) {
     57      $valgrind = 1;
     58      return 1;
     59    }
     60 
     61 # This doesn't work--it _should_!  Someone badly needs to fix this.
     62 #
     63 #   elsif ($option =~ /^-work([-_]?dir)?$/)
     64 #   {
     65 #      $workdir = shift @argv;
     66 #      return 1;
     67 #   }
     68 
     69    return 0;
     70 }
     71 
     72 
     73 # This is an "all-in-one" function.  Arguments are as follows:
     74 #
     75 #  [0] (string):  The makefile to be tested.  undef means use the last one.
     76 #  [1] (string):  Arguments to pass to make.
     77 #  [2] (string):  Answer we should get back.
     78 #  [3] (integer): Exit code we expect.  A missing code means 0 (success)
     79 
     80 $old_makefile = undef;
     81 
     82 sub run_make_test
     83 {
     84   local ($makestring, $options, $answer, $err_code) = @_;
     85 
     86   # If the user specified a makefile string, create a new makefile to contain
     87   # it.  If the first value is not defined, use the last one (if there is
     88   # one).
     89 
     90   if (! defined $makestring) {
     91     defined $old_makefile
     92       || die "run_make_test(undef) invoked before run_make_test('...')\n";
     93     $makefile = $old_makefile;
     94   } else {
     95     if (! defined($makefile)) {
     96       $makefile = &get_tmpfile();
     97     }
     98 
     99     # Make sure it ends in a newline.
    100     $makestring && $makestring !~ /\n$/s and $makestring .= "\n";
    101 
    102     # Replace @MAKEFILE@ with the makefile name and @MAKE@ with the path to
    103     # make
    104     $makestring =~ s/#MAKEFILE#/$makefile/g;
    105     $makestring =~ s/#MAKEPATH#/$mkpath/g;
    106     $makestring =~ s/#MAKE#/$make_name/g;
    107     $makestring =~ s/#PWD#/$pwd/g;
    108 
    109     # Populate the makefile!
    110     open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n";
    111     print MAKEFILE $makestring;
    112     close(MAKEFILE) || die "Failed to write $makefile: $!\n";
    113   }
    114 
    115   # Do the same processing on $answer as we did on $makestring.
    116 
    117   $answer && $answer !~ /\n$/s and $answer .= "\n";
    118   $answer =~ s/#MAKEFILE#/$makefile/g;
    119   $answer =~ s/#MAKEPATH#/$mkpath/g;
    120   $answer =~ s/#MAKE#/$make_name/g;
    121   $answer =~ s/#PWD#/$pwd/g;
    122 
    123   &run_make_with_options($makefile, $options, &get_logfile(0), $err_code);
    124   &compare_output($answer, &get_logfile(1));
    125 
    126   $old_makefile = $makefile;
    127   $makefile = undef;
    128 }
    129 
    130 # The old-fashioned way...
    131 sub run_make_with_options {
    132   local ($filename,$options,$logname,$expected_code) = @_;
    133   local($code);
    134   local($command) = $make_path;
    135 
    136   $expected_code = 0 unless defined($expected_code);
    137 
    138   # Reset to reflect this one test.
    139   $test_passed = 1;
    140 
    141   if ($filename) {
    142     $command .= " -f $filename";
    143   }
    144 
    145   if ($options) {
    146     $command .= " $options";
    147   }
    148 
    149   if ($valgrind) {
    150     print VALGRIND "\n\nExecuting: $command\n";
    151   }
    152 
    153   $code = &run_command_with_output($logname,$command);
    154 
    155   # Check to see if we have Purify errors.  If so, keep the logfile.
    156   # For this to work you need to build with the Purify flag -exit-status=yes
    157 
    158   if ($pure_log && -f $pure_log) {
    159     if ($code & 0x7000) {
    160       $code &= ~0x7000;
    161 
    162       # If we have a purify log, save it
    163       $tn = $pure_testname . ($num_of_logfiles ? ".$num_of_logfiles" : "");
    164       print("Renaming purify log file to $tn\n") if $debug;
    165       rename($pure_log, "$tn")
    166         || die "Can't rename $log to $tn: $!\n";
    167       ++$purify_errors;
    168     } else {
    169       unlink($pure_log);
    170     }
    171   }
    172 
    173   if ($code != $expected_code) {
    174     print "Error running $make_path (expected $expected_code; got $code): $command\n";
    175     $test_passed = 0;
    176     # If it's a SIGINT, stop here
    177     if ($code & 127) {
    178       print STDERR "\nCaught signal ".($code & 127)."!\n";
    179       exit($code);
    180     }
    181     return 0;
    182   }
    183 
    184   if ($profile & $vos) {
    185     system "add_profile $make_path";
    186   }
    187 
    188   1;
    189 }
    190 
    191 sub print_usage
    192 {
    193    &print_standard_usage ("run_make_tests", "[-make_path make_pathname]");
    194 }
    195 
    196 sub print_help
    197 {
    198    &print_standard_help ("-make_path",
    199           "\tYou may specify the pathname of the copy of make to run.");
    200 }
    201 
    202 sub get_this_pwd {
    203   $delete_command = 'rm -f';
    204   if ($has_POSIX) {
    205     $__pwd = POSIX::getcwd();
    206   } elsif ($vos) {
    207     $delete_command = "delete_file -no_ask";
    208     $__pwd = `++(current_dir)`;
    209   } else {
    210     # No idea... just try using pwd as a last resort.
    211     chop ($__pwd = `pwd`);
    212   }
    213 
    214   return $__pwd;
    215 }
    216 
    217 sub set_defaults
    218 {
    219    # $profile = 1;
    220    $testee = "GNU make";
    221    $make_path = "make";
    222    $tmpfilesuffix = "mk";
    223    $pwd = &get_this_pwd;
    224 }
    225 
    226 sub set_more_defaults
    227 {
    228    local($string);
    229    local($index);
    230 
    231    # Make sure we're in the C locale for those systems that support it,
    232    # so sorting, etc. is predictable.
    233    #
    234    $ENV{LANG} = 'C';
    235 
    236    # find the type of the port.  We do this up front to have a single
    237    # point of change if it needs to be tweaked.
    238    #
    239    # This is probably not specific enough.
    240    #
    241    if ($osname =~ /Windows/i || $osname =~ /MINGW32/i || $osname =~ /CYGWIN_NT/i) {
    242      $port_type = 'W32';
    243    }
    244    # Bleah, the osname is so variable on DOS.  This kind of bites.
    245    # Well, as far as I can tell if we check for some text at the
    246    # beginning of the line with either no spaces or a single space, then
    247    # a D, then either "OS", "os", or "ev" and a space.  That should
    248    # match and be pretty specific.
    249    elsif ($osname =~ /^([^ ]*|[^ ]* [^ ]*)D(OS|os|ev) /) {
    250      $port_type = 'DOS';
    251    }
    252    # Check for OS/2
    253    elsif ($osname =~ m%OS/2%) {
    254      $port_type = 'OS/2';
    255    }
    256    # Everything else, right now, is UNIX.  Note that we should integrate
    257    # the VOS support into this as well and get rid of $vos; we'll do
    258    # that next time.
    259    else {
    260      $port_type = 'UNIX';
    261    }
    262 
    263    # On DOS/Windows system the filesystem apparently can't track
    264    # timestamps with second granularity (!!).  Change the sleep time
    265    # needed to force a file to be considered "old".
    266    $wtime = $port_type eq 'UNIX' ? 1 : $port_type eq 'OS/2' ? 2 : 4;
    267 
    268    print "Port type: $port_type\n" if $debug;
    269    print "Make path: $make_path\n" if $debug;
    270 
    271    # Find the full pathname of Make.  For DOS systems this is more
    272    # complicated, so we ask make itself.
    273    my $mk = `sh -c 'echo "all:;\@echo \\\$(MAKE)" | $make_path -f-'`;
    274    chop $mk;
    275    $mk or die "FATAL ERROR: Cannot determine the value of \$(MAKE):\n
    276 'echo \"all:;\@echo \\\$(MAKE)\" | $make_path -f-' failed!\n";
    277    $make_path = $mk;
    278    print "Make\t= `$make_path'\n" if $debug;
    279 
    280    $string = `$make_path -v -f /dev/null 2> /dev/null`;
    281 
    282    $string =~ /^(GNU Make [^,\n]*)/;
    283    $testee_version = "$1\n";
    284 
    285    $string = `sh -c "$make_path -f /dev/null 2>&1"`;
    286    if ($string =~ /(.*): \*\*\* No targets\.  Stop\./) {
    287      $make_name = $1;
    288    }
    289    else {
    290      if ($make_path =~ /$pathsep([^\n$pathsep]*)$/) {
    291        $make_name = $1;
    292      }
    293      else {
    294        $make_name = $make_path;
    295      }
    296    }
    297 
    298    # prepend pwd if this is a relative path (ie, does not
    299    # start with a slash, but contains one).  Thanks for the
    300    # clue, Roland.
    301 
    302    if (index ($make_path, ":") != 1 && index ($make_path, "/") > 0)
    303    {
    304       $mkpath = "$pwd$pathsep$make_path";
    305    }
    306    else
    307    {
    308       $mkpath = $make_path;
    309    }
    310 
    311    # Get Purify log info--if any.
    312 
    313    if (exists $ENV{PURIFYOPTIONS}
    314        && $ENV{PURIFYOPTIONS} =~ /.*-logfile=([^ ]+)/) {
    315      $pure_log = $1 || '';
    316      $pure_log =~ s/%v/$make_name/;
    317      $purify_errors = 0;
    318    }
    319 
    320    $string = `sh -c "$make_path -j 2 -f /dev/null 2>&1"`;
    321    if ($string =~ /not supported/) {
    322      $parallel_jobs = 0;
    323    }
    324    else {
    325      $parallel_jobs = 1;
    326    }
    327 
    328    # Set up for valgrind, if requested.
    329 
    330    if ($valgrind) {
    331      open(VALGRIND, "> valgrind.out")
    332        || die "Cannot open valgrind.out: $!\n";
    333      #  -q --leak-check=yes
    334      exists $ENV{VALGRIND_ARGS} and $valgrind_args = $ENV{VALGRIND_ARGS};
    335      $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $valgrind_args $make_path";
    336      # F_SETFD is 2
    337      fcntl(VALGRIND, 2, 0) or die "fcntl(setfd) failed: $!\n";
    338      system("echo Starting on `date` 1>&".fileno(VALGRIND));
    339      print "Enabled valgrind support.\n";
    340    }
    341 }
    342 
    343 sub setup_for_test
    344 {
    345   $makefile = &get_tmpfile;
    346   if (-f $makefile) {
    347     unlink $makefile;
    348   }
    349 
    350   # Get rid of any Purify logs.
    351   if ($pure_log) {
    352     ($pure_testname = $testname) =~ tr,/,_,;
    353     $pure_testname = "$pure_log.$pure_testname";
    354     system("rm -f $pure_testname*");
    355     print("Purify testfiles are: $pure_testname*\n") if $debug;
    356   }
    357 }
    358 
    359 exit !&toplevel;
    360