github.com/StingNevermore/go@v0.0.0-20180120041312-3810f5bfed72/test/errchk (about)

     1  #!/usr/bin/env perl
     2  # Copyright 2009 The Go Authors. All rights reserved.
     3  # Use of this source code is governed by a BSD-style
     4  # license that can be found in the LICENSE file.
     5  
     6  # This script checks that the compilers emit the errors which we expect.
     7  # Usage: errchk COMPILER [OPTS] SOURCEFILES.  This will run the command
     8  # COMPILER [OPTS] SOURCEFILES.  The compilation is expected to fail; if
     9  # it succeeds, this script will report an error.  The stderr output of
    10  # the compiler will be matched against comments in SOURCEFILES.  For each
    11  # line of the source files which should generate an error, there should
    12  # be a comment of the form // ERROR "regexp".  If the compiler generates
    13  # an error for a line which has no such comment, this script will report
    14  # an error.  Likewise if the compiler does not generate an error for a
    15  # line which has a comment, or if the error message does not match the
    16  # <regexp>.  The <regexp> syntax is Perl but its best to stick to egrep.
    17  
    18  use POSIX;
    19  
    20  my $exitcode = 1;
    21  
    22  if(@ARGV >= 1 && $ARGV[0] eq "-0") {
    23  	$exitcode = 0;
    24  	shift;
    25  }
    26  
    27  if(@ARGV < 1) {
    28  	print STDERR "Usage: errchk COMPILER [OPTS] SOURCEFILES\n";
    29  	exit 1;
    30  }
    31  
    32  # Grab SOURCEFILES
    33  foreach(reverse 0 .. @ARGV-1) {
    34  	unless($ARGV[$_] =~ /\.(go|s)$/) {
    35  		@file = @ARGV[$_+1 .. @ARGV-1];
    36  		last;
    37  	}
    38  }
    39  
    40  # If no files have been specified try to grab SOURCEFILES from the last
    41  # argument that is an existing directory if any
    42  unless(@file) {
    43      foreach(reverse 0 .. @ARGV-1) {
    44          if(-d $ARGV[$_]) {
    45              @file = glob($ARGV[$_] . "/*.go");
    46              last;
    47          }
    48      }
    49  }
    50  
    51  foreach $file (@file) {
    52  	open(SRC, $file) || die "BUG: errchk: open $file: $!";
    53  	$src{$file} = [<SRC>];
    54  	close(SRC);
    55  }
    56  
    57  # Run command
    58  $cmd = join(' ', @ARGV);
    59  open(CMD, "exec $cmd </dev/null 2>&1 |") || die "BUG: errchk: run $cmd: $!";
    60  
    61  # gc error messages continue onto additional lines with leading tabs.
    62  # Split the output at the beginning of each line that doesn't begin with a tab.
    63  $out = join('', <CMD>);
    64  @out = split(/^(?!\t)/m, $out);
    65  
    66  close CMD;
    67  
    68  # Remove lines beginning with #, printed by go command to indicate package.
    69  @out = grep {!/^#/} @out;
    70  
    71  if($exitcode != 0 && $? == 0) {
    72  	print STDERR "BUG: errchk: command succeeded unexpectedly\n";
    73  	print STDERR @out;
    74  	exit 0;
    75  }
    76  
    77  if($exitcode == 0 && $? != 0) {
    78  	print STDERR "BUG: errchk: command failed unexpectedly\n";
    79  	print STDERR @out;
    80  	exit 0;
    81  }
    82  
    83  if(!WIFEXITED($?)) {
    84  	print STDERR "BUG: errchk: compiler crashed\n";
    85  	print STDERR @out, "\n";
    86  	exit 0;
    87  }
    88  
    89  sub bug() {
    90  	if(!$bug++) {
    91  		print STDERR "BUG: ";
    92  	}
    93  }
    94  
    95  sub chk {
    96  	my $file = shift;
    97  	my $line = 0;
    98  	my $regexp;
    99  	my @errmsg;
   100  	my @match;
   101  	foreach my $src (@{$src{$file}}) {
   102  		$line++;
   103  		next if $src =~ m|////|;  # double comment disables ERROR
   104  		next unless $src =~ m|// (GC_)?ERROR (.*)|;
   105  		my $all = $2;
   106  		if($all !~ /^"([^"]*)"/) {
   107  			print STDERR "$file:$line: malformed regexp\n";
   108  			next;
   109  		}
   110  		@errmsg = grep { /$file:$line[:[]/ } @out;
   111  		@out = grep { !/$file:$line[:[]/ } @out;
   112  		if(@errmsg == 0) {
   113  			bug();
   114  			print STDERR "errchk: $file:$line: missing expected error: '$all'\n";
   115  			next;
   116  		}
   117  		foreach my $regexp ($all =~ /"([^"]*)"/g) {
   118  			# Turn relative line number in message into absolute line number.
   119  			if($regexp =~ /LINE(([+-])([0-9]+))?/) {
   120  				my $n = $line;
   121  				if(defined($1)) {
   122  					if($2 eq "+") {
   123  						$n += int($3);
   124  					} else {
   125  						$n -= int($3);
   126  					}
   127  				}
   128  				$regexp = "$`$file:$n$'";
   129  			}
   130  	
   131  			@match = grep { /$regexp/ } @errmsg;
   132  			if(@match == 0) {
   133  				bug();
   134  				print STDERR "errchk: $file:$line: error messages do not match '$regexp'\n";
   135  				next;
   136  			}
   137  			@errmsg = grep { !/$regexp/ } @errmsg;
   138  		}
   139  		if(@errmsg != 0) {
   140  			bug();
   141  			print STDERR "errchk: $file:$line: unmatched error messages:\n";
   142  			foreach my $l (@errmsg) {
   143  				print STDERR "> $l";
   144  			}
   145  		}
   146  	}
   147  }
   148  
   149  foreach $file (@file) {
   150  	chk($file)
   151  }
   152  
   153  if(@out != 0) {
   154  	bug();
   155  	print STDERR "errchk: unmatched error messages:\n";
   156  	print STDERR "==================================================\n";
   157  	print STDERR @out;
   158  	print STDERR "==================================================\n";
   159  }
   160  
   161  exit 0;