From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 114112 invoked by alias); 10 Sep 2015 20:12:44 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 114061 invoked by uid 89); 10 Sep 2015 20:12:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.4 required=5.0 tests=AWL,BAYES_00,KAM_LAZY_DOMAIN_SECURITY,SPF_HELO_PASS,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 10 Sep 2015 20:12:35 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 1866367 for ; Thu, 10 Sep 2015 20:12:34 +0000 (UTC) Received: from c64.redhat.com (vpn-239-137.phx2.redhat.com [10.3.239.137]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t8AKCWaK003473; Thu, 10 Sep 2015 16:12:33 -0400 From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH 02/22] Testsuite: add dg-{begin|end}-multiline-output commands Date: Thu, 10 Sep 2015 20:13:00 -0000 Message-Id: <1441916913-11547-3-git-send-email-dmalcolm@redhat.com> In-Reply-To: <1441916913-11547-1-git-send-email-dmalcolm@redhat.com> References: <1441916913-11547-1-git-send-email-dmalcolm@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-IsSubscribed: yes X-SW-Source: 2015-09/txt/msg00730.txt.bz2 This patch adds an easy way to write tests for expected multiline output. For example we can test carets and underlines for a particular diagnostic with: /* { dg-begin-multiline-output "" } typedef struct _GMutex GMutex; ^~~~~~~ { dg-end-multiline-output "" } */ It is used extensively by the rest of the patch kit. multiline.exp is used by prune.exp; hence we need to load it before prune.exp via *load_gcc_lib* for the testsuites of the various non-"gcc" support libraries (e.g. boehm-gc). Question: which ChangeLog file should the change to libgo/testsuite/lib/libgo.exp go into? gcc/testsuite/ChangeLog: * lib/multiline.exp: New file. * lib/prune.exp: Load multiline.exp. (prune_gcc_output): Call into multiline.exp to handle any multiline output directives. ./ChangeLog: * libgo/testsuite/lib/libgo.exp: Load multiline.exp before prune.exp, using load_gcc_lib. boehm-gc/ChangeLog: * testsuite/lib/boehm-gc.exp: Load multiline.exp before prune.exp, using load_gcc_lib. libatomic/ChangeLog: * testsuite/lib/libatomic.exp: Load multiline.exp before prune.exp, using load_gcc_lib. libgomp/ChangeLog: * testsuite/lib/libgomp.exp: Load multiline.exp before prune.exp, using load_gcc_lib. libitm/ChangeLog: * testsuite/lib/libitm.exp: Load multiline.exp before prune.exp, using load_gcc_lib. libvtv/ChangeLog: * testsuite/lib/libvtv.exp: Load multiline.exp before prune.exp, using load_gcc_lib. --- boehm-gc/testsuite/lib/boehm-gc.exp | 1 + gcc/testsuite/lib/multiline.exp | 241 ++++++++++++++++++++++++++++++++++ gcc/testsuite/lib/prune.exp | 5 + libatomic/testsuite/lib/libatomic.exp | 1 + libgo/testsuite/lib/libgo.exp | 1 + libgomp/testsuite/lib/libgomp.exp | 1 + libitm/testsuite/lib/libitm.exp | 1 + libvtv/testsuite/lib/libvtv.exp | 1 + 8 files changed, 252 insertions(+) create mode 100644 gcc/testsuite/lib/multiline.exp diff --git a/boehm-gc/testsuite/lib/boehm-gc.exp b/boehm-gc/testsuite/lib/boehm-gc.exp index bafe7bb..d162035 100644 --- a/boehm-gc/testsuite/lib/boehm-gc.exp +++ b/boehm-gc/testsuite/lib/boehm-gc.exp @@ -31,6 +31,7 @@ load_gcc_lib target-utils.exp # For ${tool}_exit. load_gcc_lib gcc-defs.exp # For prune_gcc_output. +load_gcc_lib multiline.exp load_gcc_lib prune.exp set dg-do-what-default run diff --git a/gcc/testsuite/lib/multiline.exp b/gcc/testsuite/lib/multiline.exp new file mode 100644 index 0000000..eb72143 --- /dev/null +++ b/gcc/testsuite/lib/multiline.exp @@ -0,0 +1,241 @@ +# Copyright (C) 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# Testing of multiline output + +# We have pre-existing testcases like this: +# |typedef struct _GMutex GMutex; // { dg-message "previously declared here"} +# (using "|" here to indicate the start of a line), +# generating output like this: +# |gcc/testsuite/g++.dg/diagnostic/wrong-tag-1.C:4:16: note: 'struct _GMutex' was previously declared here +# where the location of the dg-message determines the expected line at +# which the error should be reported. +# +# To handle rich error-reporting, we want to be able to verify that we +# get output like this: +# |gcc/testsuite/g++.dg/diagnostic/wrong-tag-1.C:4:16: note: 'struct _GMutex' was previously declared here +# | typedef struct _GMutex GMutex; // { dg-message "previously declared here"} +# | ^~~~~~~ +# where the compiler's first line of output is as before, but in +# which it then echoes the source lines, adding annotations. +# +# We want to be able to write testcases that verify that the +# emitted source-and-annotations are sane. +# +# A complication here is that the source lines contain comments +# containing DejaGnu directives (such as the "dg-message" above). +# +# We punt this somewhat by only matching the beginnings of lines. +# so that we can write e.g. +# |/* { dg-begin-multiline-output "" } +# | typedef struct _GMutex GMutex; +# | ^~~~~~~ +# | { dg-end-multiline-output "" } */ +# to have the testsuite verify the expected output. + +############################################################################ +# Global variables. Although global, these are intended to only be used from +# within multiline.exp. +############################################################################ + +# The line number of the last dg-begin-multiline-output directive. +set _multiline_last_beginning_line -1 + +# A list of lists of strings. +set _multiline_expected_outputs [] + +############################################################################ +# Exported functions. +############################################################################ + +# Mark the beginning of an expected multiline output +# All lines between this and the next dg-end-multiline-output are +# expected to be seen. + +proc dg-begin-multiline-output { args } { + global _multiline_last_beginning_line + verbose "dg-begin-multiline-output: args: $args" 3 + set line [expr [lindex $args 0] + 1] + set _multiline_last_beginning_line $line +} + +# Mark the end of an expected multiline output +# All lines up to here since the last dg-begin-multiline-output are +# expected to be seen. + +proc dg-end-multiline-output { args } { + global _multiline_last_beginning_line + verbose "dg-end-multiline-output: args: $args" 3 + set line [expr [lindex $args 0] - 1] + verbose "multiline output lines: $_multiline_last_beginning_line-$line" 3 + + upvar 1 prog prog + verbose "prog: $prog" 3 + # "prog" now contains the filename + # Load it and split it into lines + + set lines [_get_lines $prog $_multiline_last_beginning_line $line] + set _multiline_last_beginning_line -1 + + verbose "lines: $lines" 3 + global _multiline_expected_outputs + lappend _multiline_expected_outputs $lines + verbose "within dg-end-multiline-output: _multiline_expected_outputs: $_multiline_expected_outputs" 3 +} + +# Hook to be called by prune.exp's prune_gcc_output to +# look for the expected multiline outputs, pruning them, +# reporting PASS for those that are found, and FAIL for +# those that weren't found. +# +# It returns a pruned version of its output. +# +# It also clears the list of expected multiline outputs. + +proc handle-multiline-outputs { text } { + global _multiline_expected_outputs + set index 0 + foreach multiline $_multiline_expected_outputs { + verbose " multiline: $multiline" 4 + set rexp [_build_multiline_regex $multiline $index] + verbose "rexp: ${rexp}" 4 + # Escape newlines in $rexp so that we can print them in + # pass/fail results. + set escaped_regex [string map {"\n" "\\n"} $rexp] + verbose "escaped_regex: ${escaped_regex}" 4 + + # Use "regsub" to attempt to prune the pattern from $text + if {[regsub -line $rexp $text "" text]} { + # Success; the multiline pattern was pruned. + pass "expected multiline pattern $index was found: \"$escaped_regex\"" + } else { + fail "expected multiline pattern $index not found: \"$escaped_regex\"" + } + + set index [expr $index + 1] + } + + # Clear the list of expected multiline outputs + set _multiline_expected_outputs [] + + return $text +} + +############################################################################ +# Internal functions +############################################################################ + +# Load FILENAME and extract the lines from FIRST_LINE +# to LAST_LINE (inclusive) as a list of strings. + +proc _get_lines { filename first_line last_line } { + verbose "_get_lines" 3 + verbose " filename: $filename" 3 + verbose " first_line: $first_line" 3 + verbose " last_line: $last_line" 3 + + set fp [open $filename r] + set file_data [read $fp] + close $fp + set data [split $file_data "\n"] + set linenum 1 + set lines [] + foreach line $data { + verbose "line $linenum: $line" 4 + if { $linenum >= $first_line && $linenum <= $last_line } { + lappend lines $line + } + set linenum [expr $linenum + 1] + } + + return $lines +} + +# Convert $multiline from a list of strings to a multiline regex +# We need to support matching arbitrary followup text on each line, +# to deal with comments containing containing DejaGnu directives. + +proc _build_multiline_regex { multiline index } { + verbose "_build_multiline_regex: $multiline $index" 4 + + set rexp "" + foreach line $multiline { + verbose " line: $line" 4 + + # We need to escape "^" and other regexp metacharacters. + set line [string map {"^" "\\^" + "(" "\\(" + ")" "\\)" + "[" "\\[" + "]" "\\]" + "." "\\." + "\\" "\\\\" + "?" "\\?" + "+" "\\+" + "*" "\\*" + "|" "\\|"} $line] + + append rexp $line + if {[string match "*^" $line] || [string match "*~" $line]} { + # Assume a line containing a caret/range. This must be + # an exact match. + } elseif {[string match "*\\|" $line]} { + # Assume a source line with a right-margin. Support + # arbitrary text in place of any whitespace before the + # right-margin, to deal with comments containing containing + # DejaGnu directives. + + # Remove final "\|": + set rexp [string range $rexp 0 [expr [string length $rexp] - 3]] + + # Trim off trailing whitespace: + set old_length [string length $rexp] + set rexp [string trimright $rexp] + set new_length [string length $rexp] + + # Replace the trimmed whitespace with "." chars to match anything: + set ws [string repeat "." [expr $old_length - $new_length]] + set rexp "${rexp}${ws}" + + # Add back the trailing '\|': + set rexp "${rexp}\\|" + } else { + # Assume that we have a quoted source line. + # Support arbitrary followup text on each line, + # to deal with comments containing containing DejaGnu + # directives. + append rexp ".*" + } + append rexp "\n" + } + + # dg.exp's dg-test trims leading whitespace from the output + # in this line: + # set comp_output [string trimleft $comp_output] + # so we can't rely on the exact leading whitespace for the + # first line in the *first* multiline regex. + # + # Trim leading whitespace from the regexp, replacing it with + # a "\s*", to match zero or more whitespace characters. + if { $index == 0 } { + set rexp [string trimleft $rexp] + set rexp "\\s*$rexp" + } + + verbose "rexp: $rexp" 4 + + return $rexp +} diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp index 8e4c203..fa10043 100644 --- a/gcc/testsuite/lib/prune.exp +++ b/gcc/testsuite/lib/prune.exp @@ -16,6 +16,8 @@ # Prune messages from gcc that aren't useful. +load_lib multiline.exp + if ![info exists TEST_ALWAYS_FLAGS] { set TEST_ALWAYS_FLAGS "" } @@ -68,6 +70,9 @@ proc prune_gcc_output { text } { # Ignore harmless warnings from Xcode 4.0. regsub -all "(^|\n)\[^\n\]*ld: warning: could not create compact unwind for\[^\n\]*" $text "" text + # Call into multiline.exp to handle any multiline output directives. + set text [handle-multiline-outputs $text] + #send_user "After:$text\n" return $text diff --git a/libatomic/testsuite/lib/libatomic.exp b/libatomic/testsuite/lib/libatomic.exp index 0491c18..cafab54 100644 --- a/libatomic/testsuite/lib/libatomic.exp +++ b/libatomic/testsuite/lib/libatomic.exp @@ -37,6 +37,7 @@ load_gcc_lib scandump.exp load_gcc_lib scanrtl.exp load_gcc_lib scantree.exp load_gcc_lib scanipa.exp +load_gcc_lib multiline.exp load_gcc_lib prune.exp load_gcc_lib target-libpath.exp load_gcc_lib wrapper.exp diff --git a/libgo/testsuite/lib/libgo.exp b/libgo/testsuite/lib/libgo.exp index 7031f63..1b0f26a 100644 --- a/libgo/testsuite/lib/libgo.exp +++ b/libgo/testsuite/lib/libgo.exp @@ -39,6 +39,7 @@ proc load_gcc_lib { filename } { set loaded_libs($filename) "" } +load_gcc_lib multiline.exp load_gcc_lib prune.exp load_gcc_lib target-libpath.exp load_gcc_lib wrapper.exp diff --git a/libgomp/testsuite/lib/libgomp.exp b/libgomp/testsuite/lib/libgomp.exp index f04b163..1040c29 100644 --- a/libgomp/testsuite/lib/libgomp.exp +++ b/libgomp/testsuite/lib/libgomp.exp @@ -14,6 +14,7 @@ load_lib dg.exp # loaded until ${tool}_target_compile is defined since it uses that # to determine default LTO options. +load_gcc_lib multiline.exp load_gcc_lib prune.exp load_gcc_lib target-libpath.exp load_gcc_lib wrapper.exp diff --git a/libitm/testsuite/lib/libitm.exp b/libitm/testsuite/lib/libitm.exp index 1361d56..0416296 100644 --- a/libitm/testsuite/lib/libitm.exp +++ b/libitm/testsuite/lib/libitm.exp @@ -28,6 +28,7 @@ load_lib dg.exp # loaded until ${tool}_target_compile is defined since it uses that # to determine default LTO options. +load_gcc_lib multiline.exp load_gcc_lib prune.exp load_gcc_lib target-libpath.exp load_gcc_lib wrapper.exp diff --git a/libvtv/testsuite/lib/libvtv.exp b/libvtv/testsuite/lib/libvtv.exp index aefcbd2..edf5fdd 100644 --- a/libvtv/testsuite/lib/libvtv.exp +++ b/libvtv/testsuite/lib/libvtv.exp @@ -28,6 +28,7 @@ load_lib dg.exp # loaded until ${tool}_target_compile is defined since it uses that # to determine default LTO options. +load_gcc_lib multiline.exp load_gcc_lib prune.exp load_gcc_lib target-libpath.exp load_gcc_lib wrapper.exp -- 1.8.5.3