URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [insight/] [dejagnu/] [lib/] [framework.exp] - Rev 1768
Go to most recent revision | Compare with Previous | Blame | View Log
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001# 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 2 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 this program; if not, write to the Free Software# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.# Please email any bugs, comments, and/or additions to this file to:# bug-dejagnu@prep.ai.mit.edu# This file was written by Rob Savoye. (rob@cygnus.com)# These variables are local to this file.# This or more warnings and a test fails.set warning_threshold 3# This or more errors and a test fails.set perror_threshold 1proc mail_file { file to subject } {if [file readable $file] {catch "exec mail -s \"$subject\" $to < $file"}}## Open the output logs#proc open_logs { } {global outdirglobal toolglobal sum_fileif { ${tool} == "" } {set tool testrun}catch "exec rm -f $outdir/$tool.sum"set sum_file [open "$outdir/$tool.sum" w]catch "exec rm -f $outdir/$tool.log"log_file -a "$outdir/$tool.log"verbose "Opening log files in $outdir"if { ${tool} == "testrun" } {set tool ""}}## Close the output logs#proc close_logs { } {global sum_filecatch "close $sum_file"}## Check build host triplet for pattern## With no arguments it returns the triplet string.#proc isbuild { pattern } {global build_tripletglobal host_tripletif ![info exists build_triplet] {set build_triplet ${host_triplet}}if [string match "" $pattern] {return $build_triplet}verbose "Checking pattern \"$pattern\" with $build_triplet" 2if [string match "$pattern" $build_triplet] {return 1} else {return 0}}## Is $board remote? Return a non-zero value if so.#proc is_remote { board } {global host_board;global target_list;verbose "calling is_remote $board" 3;# Remove any target variant specifications from the name.set board [lindex [split $board "/"] 0];# Map the host or build back into their short form.if { [board_info build name] == $board } {set board "build";} elseif { [board_info host name] == $board } {set board "host";}# We're on the "build". The check for the empty string is just for# paranoia's sake--we shouldn't ever get one. "unix" is a magic# string that should really go away someday.if { $board == "build" || $board == "unix" || $board == "" } {verbose "board is $board, not remote" 3;return 0;}if { $board == "host" } {if { [info exists host_board] && $host_board != "" } {verbose "board is $board, is remote" 3;return 1;} else {verbose "board is $board, host is local" 3;return 0;}}if { $board == "target" } {global current_target_nameif [info exists current_target_name] {# This shouldn't happen, but we'll be paranoid anyway.if { $current_target_name != "target" } {return [is_remote $current_target_name];}}return 0;}if [board_info $board exists isremote] {verbose "board is $board, isremote is [board_info $board isremote]" 3;return [board_info $board isremote];}return 1;}## If this is a canadian (3 way) cross. This means the tools are# being built with a cross compiler for another host.#proc is3way {} {global host_tripletglobal build_tripletif ![info exists build_triplet] {set build_triplet ${host_triplet}}verbose "Checking $host_triplet against $build_triplet" 2if { "$build_triplet" == "$host_triplet" } {return 0}return 1}## Check host triplet for pattern## With no arguments it returns the triplet string.#proc ishost { pattern } {global host_tripletif [string match "" $pattern] {return $host_triplet}verbose "Checking pattern \"$pattern\" with $host_triplet" 2if [string match "$pattern" $host_triplet] {return 1} else {return 0}}## Check target triplet for pattern## With no arguments it returns the triplet string.# Returns 1 if the target looked for, or 0 if not.#proc istarget { args } {global target_triplet# if no arg, return the config stringif [string match "" $args] {if [info exists target_triplet] {return $target_triplet} else {perror "No target configuration names found."}}set triplet [lindex $args 0]# now check against the cannonical nameif [info exists target_triplet] {verbose "Checking \"$triplet\" against \"$target_triplet\"" 2if [string match $triplet $target_triplet] {return 1}}# nope, no matchreturn 0}## Check to see if we're running the tests in a native environment## Returns 1 if running native, 0 if on a target.#proc isnative { } {global target_tripletglobal build_tripletif [string match $build_triplet $target_triplet] {return 1}return 0}## unknown -- called by expect if a proc is called that doesn't exist#proc unknown { args } {global errorCodeglobal errorInfoglobal exit_statusclone_output "ERROR: (DejaGnu) proc \"$args\" does not exist."if [info exists errorCode] {send_error "The error code is $errorCode\n"}if [info exists errorInfo] {send_error "The info on the error is:\n$errorInfo\n"}set exit_status 1;log_and_exit;}## Print output to stdout (or stderr) and to log file## If the --all flag (-a) option was used then all messages go the the screen.# Without this, all messages that start with a keyword are written only to the# detail log file. All messages that go to the screen will also appear in the# detail log. This should only be used by the framework itself using pass,# fail, xpass, xfail, warning, perror, note, untested, unresolved, or# unsupported procedures.#proc clone_output { message } {global sum_fileglobal all_flagif { $sum_file != "" } {puts $sum_file "$message"}regsub "^\[ \t\]*(\[^ \t\]+).*$" "$message" "\\1" firstword;case "$firstword" in {{"PASS:" "XFAIL:" "UNRESOLVED:" "UNSUPPORTED:" "UNTESTED:"} {if $all_flag {send_user "$message\n"return "$message"} else {send_log "$message\n"}}{"ERROR:" "WARNING:" "NOTE:"} {send_error "$message\n"return "$message"}default {send_user "$message\n"return "$message"}}}## Reset a few counters.#proc reset_vars {} {global test_names test_counts;global warncnt errcnt;# other miscellaneous variablesglobal prms_idglobal bug_id# reset them allset prms_id 0;set bug_id 0;set warncnt 0;set errcnt 0;foreach x $test_names {set test_counts($x,count) 0;}# Variables local to this file.global warning_threshold perror_thresholdset warning_threshold 3set perror_threshold 1}proc log_and_exit {} {global exit_status;global tool mail_logs outdir mailing_list;log_summary total;# extract version numberif {[info procs ${tool}_version] != ""} {if {[catch "${tool}_version" output]} {warning "${tool}_version failed:\n$output"}}close_logscleanupverbose -log "runtest completed at [timestamp -format %c]"if $mail_logs {mail_file $outdir/$tool.sum $mailing_list "Dejagnu Summary Log"}remote_close hostremote_close targetexit $exit_status}## Print summary of all pass/fail counts#proc log_summary { args } {global toolglobal sum_fileglobal exit_statusglobal mail_logsglobal outdirglobal mailing_listglobal current_target_nameglobal test_counts;global testcnt;if { [llength $args] == 0 } {set which "count";} else {set which [lindex $args 0];}if { [llength $args] == 0 } {clone_output "\n\t\t=== $tool Summary for $current_target_name ===\n"} else {clone_output "\n\t\t=== $tool Summary ===\n"}# If the tool set `testcnt', it wants us to do a sanity check on the# total count, so compare the reported number of testcases with the# expected number. Maintaining an accurate count in `testcnt' isn't easy# so it's not clear how often this will be used.if [info exists testcnt] {if { $testcnt > 0 } {set totlcnt 0;# total all the testcases reportedforeach x { FAIL PASS XFAIL XPASS UNTESTED UNRESOLVED UNSUPPORTED } {incr totlcnt test_counts($x,$which);}set testcnt test_counts(total,$which);if { $testcnt>$totlcnt || $testcnt<$totlcnt } {if { $testcnt > $totlcnt } {set mismatch "unreported [expr $testcnt-$totlcnt]"}if { $testcnt < $totlcnt } {set mismatch "misreported [expr $totlcnt-$testcnt]"}} else {verbose "# of testcases run $testcnt"}if [info exists mismatch] {clone_output "### ERROR: totals do not equal number of testcases run"clone_output "### ERROR: # of testcases expected $testcnt"clone_output "### ERROR: # of testcases reported $totlcnt"clone_output "### ERROR: # of testcases $mismatch\n"}}}foreach x { PASS FAIL XPASS XFAIL UNRESOLVED UNTESTED UNSUPPORTED } {set val $test_counts($x,$which);if { $val > 0 } {set mess "# of $test_counts($x,name)";if { [string length $mess] < 24 } {append mess "\t";}clone_output "$mess\t$val";}}}## Close all open files, remove temp file and core files#proc cleanup {} {global sum_fileglobal exit_statusglobal done_listglobal subdir#catch "exec rm -f [glob xgdb core *.x *.o *_soc a.out]"#catch "exec rm -f [glob -nocomplain $subdir/*.o $subdir/*.x $subdir/*_soc]"}## Setup a flag to control whether a failure is expected or not## Multiple target triplet patterns can be specified for targets# for which the test fails. A bug report ID can be specified,# which is a string without '-'.#proc setup_xfail { args } {global xfail_flagglobal xfail_prmsset xfail_prms 0set argc [ llength $args ]for { set i 0 } { $i < $argc } { incr i } {set sub_arg [ lindex $args $i ]# is a prms number. we assume this is a string with no '-' charactersif [regexp "^\[^\-\]+$" $sub_arg] {set xfail_prms $sub_argcontinue}if [istarget $sub_arg] {set xfail_flag 1continue}}}# check to see if a conditional xfail is triggered# message {targets} {include} {exclude}##proc check_conditional_xfail { args } {global compiler_flagsset all_args [lindex $args 0]set message [lindex $all_args 0]set target_list [lindex $all_args 1]verbose "Limited to targets: $target_list" 3# get the list of flags to look forset includes [lindex $all_args 2]verbose "Will search for options $includes" 3# get the list of flags to excludeif { [llength $all_args] > 3 } {set excludes [lindex $all_args 3]verbose "Will exclude for options $excludes" 3} else {set excludes ""}# loop through all the targets, checking the options for each oneverbose "Compiler flags are: $compiler_flags" 2set incl_hit 0set excl_hit 0foreach targ $target_list {if [istarget $targ] {# look through the compiler options for flags we want to see# this is really messy cause each set of options to look for# may also be a list. We also want to find each element of the# list, regardless of order to make sure they're found.# So we look for lists in side of lists, and make sure all# the elements match before we decide this is legit.for { set i 0 } { $i < [llength $includes] } { incr i } {set incl_hit 0set opt [lindex $includes $i]verbose "Looking for $opt to include in the compiler flags" 2foreach j "$opt" {if [string match "* $j *" $compiler_flags] {verbose "Found $j to include in the compiler flags" 2incr incl_hit}}# if the number of hits we get is the same as the number of# specified options, then we got a matchif {$incl_hit == [llength $opt]} {break} else {set incl_hit 0}}# look through the compiler options for flags we don't# want to seefor { set i 0 } { $i < [llength $excludes] } { incr i } {set excl_hit 0set opt [lindex $excludes $i]verbose "Looking for $opt to exclude in the compiler flags" 2foreach j "$opt" {if [string match "* $j *" $compiler_flags] {verbose "Found $j to exclude in the compiler flags" 2incr excl_hit}}# if the number of hits we get is the same as the number of# specified options, then we got a matchif {$excl_hit == [llength $opt]} {break} else {set excl_hit 0}}# if we got a match for what to include, but didn't find any reasons# to exclude this, then we got a match! So return one to turn this into# an expected failure.if {$incl_hit && ! $excl_hit } {verbose "This is a conditional match" 2return 1} else {verbose "This is not a conditional match" 2return 0}}}return 0}## Clear the xfail flag for a particular target#proc clear_xfail { args } {global xfail_flagglobal xfail_prmsset argc [ llength $args ]for { set i 0 } { $i < $argc } { incr i } {set sub_arg [ lindex $args $i ]case $sub_arg in {"*-*-*" { # is a configuration tripletif [istarget $sub_arg] {set xfail_flag 0set xfail_prms 0}continue}}}}## Record that a test has passed or failed (perhaps unexpectedly)## This is an internal procedure, only used in this file.#proc record_test { type message args } {global exit_statusglobal prms_id bug_idglobal xfail_flag xfail_prmsglobal errcnt warncntglobal warning_threshold perror_thresholdglobal pf_prefixif { [llength $args] > 0 } {set count [lindex $args 0];} else {set count 1;}if [info exists pf_prefix] {set message [concat $pf_prefix " " $message];}# If we have too many warnings or errors,# the output of the test can't be considered correct.if { $warning_threshold > 0 && $warncnt >= $warning_threshold|| $perror_threshold > 0 && $errcnt >= $perror_threshold } {verbose "Error/Warning threshold exceeded: \$errcnt $warncnt (max. $perror_threshold $warning_threshold)"set type UNRESOLVED}incr_count $type;switch $type {PASS {if $prms_id {set message [concat $message "\t(PRMS $prms_id)"]}}FAIL {set exit_status 1if $prms_id {set message [concat $message "\t(PRMS $prms_id)"]}}XPASS {set exit_status 1if { $xfail_prms != 0 } {set message [concat $message "\t(PRMS $xfail_prms)"]}}XFAIL {if { $xfail_prms != 0 } {set message [concat $message "\t(PRMS $xfail_prms)"]}}UNTESTED {# The only reason we look at the xfail stuff is to pick up# `xfail_prms'.if { $xfail_flag && $xfail_prms != 0 } {set message [concat $message "\t(PRMS $xfail_prms)"]} elseif $prms_id {set message [concat $message "\t(PRMS $prms_id)"]}}UNRESOLVED {set exit_status 1# The only reason we look at the xfail stuff is to pick up# `xfail_prms'.if { $xfail_flag && $xfail_prms != 0 } {set message [concat $message "\t(PRMS $xfail_prms)"]} elseif $prms_id {set message [concat $message "\t(PRMS $prms_id)"]}}UNSUPPORTED {# The only reason we look at the xfail stuff is to pick up# `xfail_prms'.if { $xfail_flag && $xfail_prms != 0 } {set message [concat $message "\t(PRMS $xfail_prms)"]} elseif $prms_id {set message [concat $message "\t(PRMS $prms_id)"]}}default {perror "record_test called with bad type `$type'"set errcnt 0return}}if $bug_id {set message [concat $message "\t(BUG $bug_id)"]}global multipass_nameif { $multipass_name != "" } {set message [format "$type: %s: $message" "$multipass_name"]} else {set message "$type: $message"}clone_output "$message"# If a command name exists in the $local_record_procs associative# array for this type of result, then invoke it.set lowcase_type [string tolower $type]global local_record_procsif {[info exists local_record_procs($lowcase_type)]} {$local_record_procs($lowcase_type) "$message"}# Reset these so they're ready for the next test case. We don't reset# prms_id or bug_id here. There may be multiple tests for them. Instead# they are reset in the main loop after each test. It is also the# testsuite driver's responsibility to reset them after each testcase.set warncnt 0set errcnt 0set xfail_flag 0set xfail_prms 0}## Record that a test has passed#proc pass { message } {global xfail_flag compiler_conditional_xfail_data# if we have a conditional xfail setup, then see if our compiler flags matchif [ info exists compiler_conditional_xfail_data ] {if [check_conditional_xfail $compiler_conditional_xfail_data] {set xfail_flag 1}unset compiler_conditional_xfail_data}if $xfail_flag {record_test XPASS $message} else {record_test PASS $message}}## Record that a test has failed#proc fail { message } {global xfail_flag compiler_conditional_xfail_data# if we have a conditional xfail setup, then see if our compiler flags matchif [ info exists compiler_conditional_xfail_data ] {if [check_conditional_xfail $compiler_conditional_xfail_data] {set xfail_flag 1}unset compiler_conditional_xfail_data}if $xfail_flag {record_test XFAIL $message} else {record_test FAIL $message}}## Record that a test has passed unexpectedly#proc xpass { message } {record_test XPASS $message}## Record that a test has failed unexpectedly#proc xfail { message } {record_test XFAIL $message}## Set warning threshold#proc set_warning_threshold { threshold } {set warning_threshold $threshold}## Get warning threshold#proc get_warning_threshold { } {return $warning_threshold}## Prints warning messages# These are warnings from the framework, not from the tools being tested.# It takes a string, and an optional number and returns nothing.#proc warning { args } {global warncntif { [llength $args] > 1 } {set warncnt [lindex $args 1]} else {incr warncnt}set message [lindex $args 0]clone_output "WARNING: $message"global errorInfoif [info exists errorInfo] {unset errorInfo}}## Prints error messages# These are errors from the framework, not from the tools being tested.# It takes a string, and an optional number and returns nothing.#proc perror { args } {global errcntif { [llength $args] > 1 } {set errcnt [lindex $args 1]} else {incr errcnt}set message [lindex $args 0]clone_output "ERROR: $message"global errorInfoif [info exists errorInfo] {unset errorInfo}}## Prints informational messages## These are messages from the framework, not from the tools being tested.# This means that it is currently illegal to call this proc outside# of dejagnu proper.#proc note { message } {clone_output "NOTE: $message"# ??? It's not clear whether we should do this. Let's not, and only do# so if we find a real need for it.#global errorInfo#if [info exists errorInfo] {# unset errorInfo#}}## untested -- mark the test case as untested#proc untested { message } {record_test UNTESTED $message}## Mark the test case as unresolved#proc unresolved { message } {record_test UNRESOLVED $message}## Mark the test case as unsupported## Usually this is used for a test that is missing OS support.#proc unsupported { message } {record_test UNSUPPORTED $message}## Set up the values in the test_counts array (name and initial totals).#proc init_testcounts { } {global test_counts test_names;set test_counts(TOTAL,name) "testcases run"set test_counts(PASS,name) "expected passes"set test_counts(FAIL,name) "unexpected failures"set test_counts(XFAIL,name) "expected failures"set test_counts(XPASS,name) "unexpected successes"set test_counts(WARNING,name) "warnings"set test_counts(ERROR,name) "errors"set test_counts(UNSUPPORTED,name) "unsupported tests"set test_counts(UNRESOLVED,name) "unresolved testcases"set test_counts(UNTESTED,name) "untested testcases"set j "";foreach i [lsort [array names test_counts]] {regsub ",.*$" "$i" "" i;if { $i == $j } {continue;}set test_counts($i,total) 0;lappend test_names $i;set j $i;}}## Increment NAME in the test_counts array; the amount to increment can be# is optional (defaults to 1).#proc incr_count { name args } {global test_counts;if { [llength $args] == 0 } {set count 1;} else {set count [lindex $args 0];}if [info exists test_counts($name,count)] {incr test_counts($name,count) $count;incr test_counts($name,total) $count;} else {perror "$name doesn't exist in incr_count"}}## Create an exp_continue proc if it doesn't exist## For compatablity with old versions.#global argv0if ![info exists argv0] {proc exp_continue { } {continue -expect}}
Go to most recent revision | Compare with Previous | Blame | View Log
