...
Run Format

Text file test/errchk

Documentation: 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	# 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;

View as plain text