diff options
Diffstat (limited to 'test/errchk')
-rwxr-xr-x | test/errchk | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/test/errchk b/test/errchk new file mode 100755 index 000000000..6b00570bd --- /dev/null +++ b/test/errchk @@ -0,0 +1,147 @@ +#!/usr/bin/perl +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# This script checks that the compilers emit the errors which we expect. +# Usage: errchk COMPILER [OPTS] SOURCEFILES. This will run the command +# COMPILER [OPTS] SOURCEFILES. The compilation is expected to fail; if +# it succeeds, this script will report an error. The stderr output of +# the compiler will be matched against comments in SOURCEFILES. For each +# line of the source files which should generate an error, there should +# be a comment of the form // ERROR "regexp". If the compiler generates +# an error for a line which has no such comment, this script will report +# an error. Likewise if the compiler does not generate an error for a +# line which has a comment, or if the error message does not match the +# <regexp>. The <regexp> syntax is Perl but its best to stick to egrep. + +use POSIX; + +my $exitcode = 1; + +if(@ARGV >= 1 && $ARGV[0] eq "-0") { + $exitcode = 0; + shift; +} + +if(@ARGV < 1) { + print STDERR "Usage: errchk COMPILER [OPTS] SOURCEFILES\n"; + exit 1; +} + +# Grab SOURCEFILES +foreach(reverse 0 .. @ARGV-1) { + unless($ARGV[$_] =~ /\.go$/) { + @file = @ARGV[$_+1 .. @ARGV-1]; + last; + } +} + +foreach $file (@file) { + open(SRC, $file) || die "BUG: errchk: open $file: $!"; + $src{$file} = [<SRC>]; + close(SRC); +} + +# Run command +$cmd = join(' ', @ARGV); +open(CMD, "exec $cmd </dev/null 2>&1 |") || die "BUG: errchk: run $cmd: $!"; + +# 6g error messages continue onto additional lines with leading tabs. +# Split the output at the beginning of each line that doesn't begin with a tab. +$out = join('', <CMD>); +@out = split(/^(?!\t)/m, $out); + +close CMD; + +if($exitcode != 0 && $? == 0) { + print STDERR "BUG: errchk: command succeeded unexpectedly\n"; + print STDERR @out; + exit 0; +} + +if($exitcode == 0 && $? != 0) { + print STDERR "BUG: errchk: command failed unexpectedly\n"; + print STDERR @out; + exit 0; +} + +if(!WIFEXITED($?)) { + print STDERR "BUG: errchk: compiler crashed\n"; + print STDERR @out, "\n"; + exit 0; +} + +sub bug() { + if(!$bug++) { + print STDERR "BUG: "; + } +} + +sub chk { + my $file = shift; + my $line = 0; + my $regexp; + my @errmsg; + my @match; + foreach my $src (@{$src{$file}}) { + $line++; + next if $src =~ m|////|; # double comment disables ERROR + next unless $src =~ m|// (GC_)?ERROR (.*)|; + my $all = $2; + if($all !~ /^"([^"]*)"/) { + print STDERR "$file:$line: malformed regexp\n"; + next; + } + @errmsg = grep { /$file:$line[:[]/ } @out; + @out = grep { !/$file:$line[:[]/ } @out; + if(@errmsg == 0) { + bug(); + print STDERR "errchk: $file:$line: missing expected error: '$all'\n"; + next; + } + foreach my $regexp ($all =~ /"([^"]*)"/g) { + # Turn relative line number in message into absolute line number. + if($regexp =~ /LINE(([+-])([0-9]+))?/) { + my $n = $line; + if(defined($1)) { + if($2 eq "+") { + $n += int($3); + } else { + $n -= int($3); + } + } + $regexp = "$`$file:$n$'"; + } + + @match = grep { /$regexp/ } @errmsg; + if(@match == 0) { + bug(); + print STDERR "errchk: $file:$line: error messages do not match '$regexp'\n"; + next; + } + @errmsg = grep { !/$regexp/ } @errmsg; + } + if(@errmsg != 0) { + bug(); + print STDERR "errchk: $file:$line: unmatched error messages:\n"; + foreach my $l (@errmsg) { + print STDERR "> $l"; + } + } + } +} + +foreach $file (@file) { + chk($file) +} + +if(@out != 0) { + bug(); + print STDERR "errchk: unmatched error messages:\n"; + print STDERR "==================================================\n"; + print STDERR @out; + print STDERR "==================================================\n"; +} + +exit 0; |