Home | History | Annotate | Download | only in test
      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 foreach $file (@file) {
     41 	open(SRC, $file) || die "BUG: errchk: open $file: $!";
     42 	$src{$file} = [<SRC>];
     43 	close(SRC);
     44 }
     45 
     46 # Run command
     47 $cmd = join(' ', @ARGV);
     48 open(CMD, "exec $cmd </dev/null 2>&1 |") || die "BUG: errchk: run $cmd: $!";
     49 
     50 # gc error messages continue onto additional lines with leading tabs.
     51 # Split the output at the beginning of each line that doesn't begin with a tab.
     52 $out = join('', <CMD>);
     53 @out = split(/^(?!\t)/m, $out);
     54 
     55 close CMD;
     56 
     57 if($exitcode != 0 && $? == 0) {
     58 	print STDERR "BUG: errchk: command succeeded unexpectedly\n";
     59 	print STDERR @out;
     60 	exit 0;
     61 }
     62 
     63 if($exitcode == 0 && $? != 0) {
     64 	print STDERR "BUG: errchk: command failed unexpectedly\n";
     65 	print STDERR @out;
     66 	exit 0;
     67 }
     68 
     69 if(!WIFEXITED($?)) {
     70 	print STDERR "BUG: errchk: compiler crashed\n";
     71 	print STDERR @out, "\n";
     72 	exit 0;
     73 }
     74 
     75 sub bug() {
     76 	if(!$bug++) {
     77 		print STDERR "BUG: ";
     78 	}
     79 }
     80 
     81 sub chk {
     82 	my $file = shift;
     83 	my $line = 0;
     84 	my $regexp;
     85 	my @errmsg;
     86 	my @match;
     87 	foreach my $src (@{$src{$file}}) {
     88 		$line++;
     89 		next if $src =~ m|////|;  # double comment disables ERROR
     90 		next unless $src =~ m|// (GC_)?ERROR (.*)|;
     91 		my $all = $2;
     92 		if($all !~ /^"([^"]*)"/) {
     93 			print STDERR "$file:$line: malformed regexp\n";
     94 			next;
     95 		}
     96 		@errmsg = grep { /$file:$line[:[]/ } @out;
     97 		@out = grep { !/$file:$line[:[]/ } @out;
     98 		if(@errmsg == 0) {
     99 			bug();
    100 			print STDERR "errchk: $file:$line: missing expected error: '$all'\n";
    101 			next;
    102 		}
    103 		foreach my $regexp ($all =~ /"([^"]*)"/g) {
    104 			# Turn relative line number in message into absolute line number.
    105 			if($regexp =~ /LINE(([+-])([0-9]+))?/) {
    106 				my $n = $line;
    107 				if(defined($1)) {
    108 					if($2 eq "+") {
    109 						$n += int($3);
    110 					} else {
    111 						$n -= int($3);
    112 					}
    113 				}
    114 				$regexp = "$`$file:$n$'";
    115 			}
    116 	
    117 			@match = grep { /$regexp/ } @errmsg;
    118 			if(@match == 0) {
    119 				bug();
    120 				print STDERR "errchk: $file:$line: error messages do not match '$regexp'\n";
    121 				next;
    122 			}
    123 			@errmsg = grep { !/$regexp/ } @errmsg;
    124 		}
    125 		if(@errmsg != 0) {
    126 			bug();
    127 			print STDERR "errchk: $file:$line: unmatched error messages:\n";
    128 			foreach my $l (@errmsg) {
    129 				print STDERR "> $l";
    130 			}
    131 		}
    132 	}
    133 }
    134 
    135 foreach $file (@file) {
    136 	chk($file)
    137 }
    138 
    139 if(@out != 0) {
    140 	bug();
    141 	print STDERR "errchk: unmatched error messages:\n";
    142 	print STDERR "==================================================\n";
    143 	print STDERR @out;
    144 	print STDERR "==================================================\n";
    145 }
    146 
    147 exit 0;
    148