加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
runtest.exp 50.41 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903
# runtest.exp -- Test framework driver
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
# 2001, 2002, 2003, 2012 Free Software Foundation, Inc.
#
# This file is part of DejaGnu.
#
# DejaGnu 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.
#
# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
# This file was written by Rob Savoye <rob@welcomehome.org>.
set frame_version 1.6
if {![info exists argv0]} {
send_error "Must use a version of Expect greater than 5.0\n"
exit 1
}
# trap some signals so we know whats happening. These definitions are only
# temporary until we read in the library stuff
#
trap { send_user "\ninterrupted by user\n"; exit 130 } SIGINT
trap { send_user "\nquit\n"; exit 131 } SIGQUIT
trap { send_user "\nterminated\n"; exit 143 } SIGTERM
#
# Initialize a few global variables used by all tests.
# `reset_vars' resets several of these, we define them here to document their
# existence. In fact, it would be nice if all globals used by some interface
# of dejagnu proper were documented here.
#
# Keep these all lowercase. Interface variables used by the various
# testsuites (eg: the gcc testsuite) should be in all capitals
# (eg: TORTURE_OPTIONS).
#
set mail_logs 0 ;# flag for mailing of summary and diff logs
set psum_file "latest" ;# file name of previous summary to diff against
set exit_status 0 ;# exit code returned by this program
set xfail_flag 0 ;# indicates that a failure is expected
set xfail_prms 0 ;# GNATS prms id number for this expected failure
set kfail_flag 0 ;# indicates that it is a known failure
set kfail_prms 0 ;# bug id for the description of the known failure
set sum_file "" ;# name of the file that contains the summary log
set base_dir "" ;# the current working directory
set xml_file_name "" ;# name of the xml output if requested
set xml_file "" ;# handle on the xml file if requested
set xml 0 ;# flag for requesting xml
set logname "" ;# the users login name
set prms_id 0 ;# GNATS prms id number
set bug_id 0 ;# optional bug id number
set dir "" ;# temp variable for directory names
set srcdir "." ;# source directory containing the test suite
set ignoretests "" ;# list of tests to not execute
set objdir "." ;# directory where test case binaries live
set reboot 0
set configfile site.exp ;# (local to this file)
set multipass "" ;# list of passes and var settings
set errno ""; ;#
set exit_error 1 ;# Toggle for whether to set the exit status
;# on Tcl bugs in test case drivers.
#
# These describe the host and target environments.
#
set build_triplet "" ;# type of architecture to run tests on
set build_os "" ;# type of os the tests are running on
set build_vendor "" ;# vendor name of the OS or workstation the test are running on
set build_cpu "" ;# type of the cpu tests are running on
set host_triplet "" ;# type of architecture to run tests on, sometimes remotely
set host_os "" ;# type of os the tests are running on
set host_vendor "" ;# vendor name of the OS or workstation the test are running on
set host_cpu "" ;# type of the cpu tests are running on
set target_triplet "" ;# type of architecture to run tests on, final remote
set target_os "" ;# type of os the tests are running on
set target_vendor "" ;# vendor name of the OS or workstation the test are running on
set target_cpu "" ;# type of the cpu tests are running on
set target_alias "" ;# standard abbreviation of target
set compiler_flags "" ;# the flags used by the compiler
#
# some convenience abbreviations
#
if {![info exists hex]} {
set hex "0x\[0-9A-Fa-f\]+"
}
if {![info exists decimal]} {
set decimal "\[0-9\]+"
}
#
# set the base dir (current working directory)
#
set base_dir [pwd]
#
# These are tested in case they are not initialized in $configfile. They are
# tested here instead of the init module so they can be overridden by command
# line options.
#
if {![info exists all_flag]} {
set all_flag 0
}
if {![info exists binpath]} {
set binpath ""
}
if {![info exists debug]} {
set debug 0
}
if {![info exists options]} {
set options ""
}
if {![info exists outdir]} {
set outdir "."
}
if {![info exists reboot]} {
set reboot 1
}
if {![info exists tracelevel]} {
set tracelevel 0
}
if {![info exists verbose]} {
set verbose 0
}
if {![info exists log_dialog]} {
set log_dialog 0
}
#
# verbose [-n] [-log] [--] message [level]
#
# Print MESSAGE if the verbose level is >= LEVEL.
# The default value of LEVEL is 1.
# "-n" says to not print a trailing newline.
# "-log" says to add the text to the log file even if it won't be printed.
# Note that the apparent behaviour of `send_user' dictates that if the message
# is printed it is also added to the log file.
# Use "--" if MESSAGE begins with "-".
#
# This is defined here rather than in framework.exp so we can use it
# while still loading in the support files.
#
proc verbose { args } {
global verbose
set newline 1
set logfile 0
set i 0
if { [string index [lindex $args 0] 0] == "-" } {
for { set i 0 } { $i < [llength $args] } { incr i } {
if { [lindex $args $i] == "--" } {
incr i
break
} elseif { [lindex $args $i] == "-n" } {
set newline 0
} elseif { [lindex $args $i] == "-log" } {
set logfile 1
} elseif { [lindex $args $i] == "-x" } {
set xml 1
} elseif { [string index [lindex $args $i] 0] == "-" } {
clone_output "ERROR: verbose: illegal argument: [lindex $args $i]"
return
} else {
break
}
}
if { [llength $args] == $i } {
clone_output "ERROR: verbose: nothing to print"
return
}
}
set level 1
if { [llength $args] > $i + 1 } {
set level [lindex $args [expr { $i + 1 }]]
}
set message [lindex $args $i]
if { $verbose >= $level } {
# We assume send_user also sends the text to the log file (which
# appears to be the case though the docs aren't clear on this).
if { $newline } {
send_user -- "$message\n"
} else {
send_user -- "$message"
}
} elseif { $logfile } {
if { $newline } {
send_log -- "$message\n"
} else {
send_log -- "$message"
}
}
}
#
# Transform a tool name to get the installed name.
# target_triplet is the canonical target name. target_alias is the
# target name used when configure was run.
#
proc transform { name } {
global target_triplet
global target_alias
global host_triplet
global board
if {[string match $target_triplet $host_triplet]} {
return $name
}
if {[string match "native" $target_triplet]} {
return $name
}
if {[board_info host exists no_transform_name]} {
return $name
}
if {[string match "" $target_triplet]} {
return $name
} else {
if {[info exists board]} {
if {[board_info $board exists target_install]} {
set target_install [board_info $board target_install]
}
}
if {[target_info exists target_install]} {
set target_install [target_info target_install]
}
if {[info exists target_alias]} {
set tmp ${target_alias}-${name}
} elseif {[info exists target_install]} {
if { [lsearch -exact $target_install $target_alias] >= 0 } {
set tmp ${target_alias}-${name}
} else {
set tmp "[lindex $target_install 0]-${name}"
}
}
verbose "Transforming $name to $tmp"
return $tmp
}
}
#
# findfile arg0 [arg1] [arg2]
#
# Find a file and see if it exists. If you only care about the false
# condition, then you'll need to pass a null "" for arg1.
# arg0 is the filename to look for. If the only arg,
# then that's what gets returned. If this is the
# only arg, then if it exists, arg0 gets returned.
# if it doesn't exist, return only the prog name.
# arg1 is optional, and it's what gets returned if
# the file exists.
# arg2 is optional, and it's what gets returned if
# the file doesn't exist.
#
proc findfile { args } {
# look for the file
verbose "Seeing if [lindex $args 0] exists." 2
if {[file exists [lindex $args 0]]} {
if { [llength $args] > 1 } {
verbose "Found file, returning [lindex $args 1]"
return [lindex $args 1]
} else {
verbose "Found file, returning [lindex $args 0]"
return [lindex $args 0]
}
} else {
if { [llength $args] > 2 } {
verbose "Didn't find file [lindex $args 0], returning [lindex $args 2]"
return [lindex $args 2]
} else {
verbose "Didn't find file, returning [file tail [lindex $args 0]]"
return [transform [file tail [lindex $args 0]]]
}
}
}
#
# load_file [-1] [--] file1 [ file2 ... ]
#
# Utility to source a file. All are sourced in order unless the flag "-1"
# is given in which case we stop after finding the first one.
# The result is 1 if a file was found, 0 if not.
# If a tcl error occurs while sourcing a file, we print an error message
# and exit.
#
proc load_file { args } {
set i 0
set only_one 0
if { [lindex $args $i] == "-1" } {
set only_one 1
incr i
}
if { [lindex $args $i] == "--" } {
incr i
}
set found 0
foreach file [lrange $args $i end] {
verbose "Looking for $file" 2
# In Tcl, "file exists" fails if the filename looks like
# ~/FILE and the environment variable HOME does not exist.
if {! [catch {file exists $file} result] && $result} {
set found 1
verbose "Found $file"
if { [catch "uplevel #0 source $file"] == 1 } {
send_error "ERROR: tcl error sourcing $file.\n"
global errorInfo
if {[info exists errorInfo]} {
send_error "$errorInfo\n"
}
exit 1
}
if { $only_one } {
break
}
}
}
return $found
}
#
# search_and_load_file -- search DIRLIST looking for FILELIST.
# TYPE is used when displaying error and progress messages.
#
proc search_and_load_file { type filelist dirlist } {
set found 0
foreach dir $dirlist {
foreach initfile $filelist {
verbose "Looking for $type ${dir}/${initfile}" 2
if {[file exists [file join ${dir} ${initfile}]]} {
set found 1
set error ""
if { ${type} != "library file" } {
send_user "Using ${dir}/${initfile} as ${type}.\n"
} else {
verbose "Loading ${dir}/${initfile}"
}
if {[catch "uplevel #0 source ${dir}/${initfile}" error] == 1} {
global errorInfo
send_error "ERROR: tcl error sourcing ${type} ${dir}/${initfile}.\n${error}\n"
if {[info exists errorInfo]} {
send_error "$errorInfo\n"
}
exit 1
}
break
}
}
if { $found } {
break
}
}
return $found
}
#
# Give a usage statement.
#
proc usage { } {
global tool
send_user "USAGE: runtest \[options...\]\n"
send_user "\t--all, -a\t\tPrint all test output to screen\n"
send_user "\t--build \[triplet\]\tThe canonical triplet of the build machine\n"
send_user "\t--debug\t\t\tSet expect debugging ON\n"
send_user "\t--directory name\tRun only the tests in directory 'name'\n"
send_user "\t--help\t\t\tPrint help text\n"
send_user "\t--host \[triplet\]\tThe canonical triplet of the host machine\n"
send_user "\t--host_board \[name\]\tThe host board to use\n"
send_user "\t--ignore \[name(s)\]\tThe names of specific tests to ignore\n"
send_user "\t--log_dialog\t\t\Emit Expect output on stdout\n"
send_user "\t--mail \[name(s)\]\tWhom to mail the results to\n"
send_user "\t--objdir \[name\]\t\tThe test suite binary directory\n"
send_user "\t--outdir \[name\]\t\tThe directory to put logs in\n"
send_user "\t--reboot \[name\]\t\tReboot the target (if supported)\n"
send_user "\t--srcdir \[name\]\t\tThe test suite source code directory\n"
send_user "\t--status\t\tSet the exit status to fail on Tcl errors\n"
send_user "\t--strace \[number\]\tSet expect tracing ON\n"
send_user "\t--target \[triplet\]\tThe canonical triplet of the target board\n"
send_user "\t--target_board \[name(s)\] The list of target boards to run tests on\n"
send_user "\t--tool \[name(s)\]\tRun tests on these tools\n"
send_user "\t--tool_exec \[name\]\tThe path to the tool executable to test\n"
send_user "\t--tool_opts \[options\]\tA list of additional options to pass to the tool\n"
send_user "\t--verbose, -v\t\tProduce verbose output\n"
send_user "\t--version, -V\t\tPrint all relevant version numbers\n"
send_user "\t--xml\[=name\], -x\tTurn on XML output generation\n"
send_user "\t--D\[0-1\]\t\tTcl debugger\n"
send_user "\tscript.exp\[=arg(s)\]\tRun these tests only\n"
if { [info exists tool] } {
if { [info procs ${tool}_option_help] != "" } {
${tool}_option_help
}
}
}
#
# Parse the arguments the first time looking for these. We will ultimately
# parse them twice. Things are complicated because:
# - we want to parse --verbose early on
# - we don't want config files to override command line arguments
# (eg: $base_dir/$configfile vs --host/--target)
# - we need some command line arguments before we can process some config files
# (eg: --objdir before $objdir/$configfile, --host/--target before $DEJAGNU)
# The use of `arg_host_triplet' and `arg_target_triplet' lets us avoid parsing
# the arguments three times.
#
set arg_host_triplet ""
set arg_target_triplet ""
set arg_build_triplet ""
set argc [ llength $argv ]
for { set i 0 } { $i < $argc } { incr i } {
set option [lindex $argv $i]
# make all options have two hyphens
switch -glob -- $option {
"--*" {
}
"-*" {
set option "-$option"
}
}
# split out the argument for options that take them
switch -glob -- $option {
"--*=*" {
regexp {^[^=]*=(.*)$} $option nil optarg
}
"--bu*" -
"--ho*" -
"--ig*" -
"--m*" -
"--n*" -
"--ob*" -
"--ou*" -
"--sr*" -
"--str*" -
"--ta*" -
"--di*" -
"--to*" {
incr i
set optarg [lindex $argv $i]
}
}
switch -glob -- $option {
"--bu*" { # (--build) the build host configuration
set arg_build_triplet $optarg
continue
}
"--host_bo*" {
set host_board $optarg
continue
}
"--ho*" { # (--host) the host configuration
set arg_host_triplet $optarg
continue
}
"--ob*" { # (--objdir) where the test case object code lives
set objdir $optarg
continue
}
"--sr*" { # (--srcdir) where the testsuite source code lives
set srcdir $optarg
continue
}
"--target_bo*" {
set target_list $optarg
continue
}
"--ta*" { # (--target) the target configuration
set arg_target_triplet $optarg
continue
}
"--tool_opt*" {
set TOOL_OPTIONS $optarg
continue
}
"--tool_exec*" {
set TOOL_EXECUTABLE $optarg
continue
}
"--to*" { # (--tool) specify tool name
set tool $optarg
set comm_line_tool $optarg
continue
}
"--di*" {
set cmdline_dir_to_run $optarg
continue
}
"--v" -
"--verb*" { # (--verbose) verbose output
incr verbose
continue
}
"[A-Z0-9_-.]*=*" { # process makefile style args like CC=gcc, etc...
if {[regexp "^(\[A-Z0-9_-\]+)=(.*)$" $option junk var val]} {
set $var $val
verbose "$var is now $val"
append makevars "set $var $val;" ;# FIXME: Used anywhere?
unset junk var val
} else {
send_error "Illegal variable specification:\n"
send_error "$option\n"
}
continue
}
}
}
verbose "Verbose level is $verbose"
#
# get the users login name
#
if {[string match "" $logname]} {
if {[info exists env(USER)]} {
set logname $env(USER)
} else {
if {[info exists env(LOGNAME)]} {
set logname $env(LOGNAME)
} else {
# try getting it with whoami
catch "set logname [exec whoami]" tmp
if {[string match "*couldn't find*to execute*" $tmp]} {
# try getting it with who am i
unset tmp
catch "set logname [exec who am i]" tmp
if {[string match "*Command not found*" $tmp]} {
send_user "ERROR: couldn't get the users login name\n"
set logname "Unknown"
} else {
set logname [lindex [split $logname " !"] 1]
}
}
}
}
}
#
# lookfor_file -- try to find a file by searching up multiple directory levels
#
proc lookfor_file { dir name } {
foreach x ". .. ../.. ../../.. ../../../.." {
verbose "$dir/$x/$name" 2
if {[file exists [file join $dir $name]]} {
return [file join $dir $name]
}
set dir [remote_file build dirname $dir]
}
return ""
}
#
# load_lib -- load a library by sourcing it
#
# If there a multiple files with the same name, stop after the first one found.
# The order is first look in the install dir, then in a parallel dir in the
# source tree (up one or two levels), then in the current dir.
#
proc load_lib { file } {
global verbose libdir libdirs srcdir base_dir execpath tool
global loaded_libs
if {[info exists loaded_libs($file)]} {
return
}
set loaded_libs($file) ""
set search_dirs [list ../lib $libdir $libdir/lib [file dirname [file dirname $srcdir]]/dejagnu/lib $srcdir/lib $execpath/lib . [file dirname [file dirname [file dirname $srcdir]]]/dejagnu/lib]
if {[info exists libdirs]} {
lappend search_dirs $libdirs
}
if { [search_and_load_file "library file" $file $search_dirs ] == 0 } {
send_error "ERROR: Couldn't find library file $file.\n"
exit 1
}
}
verbose "Login name is $logname"
#
# Begin sourcing the config files.
# All are sourced in order.
#
# Search order:
# $base_dir/$configfile -> $objdir/$configfile ->
# installed -> $DEJAGNU -> $HOME/.dejagnurc
#
# For the normal case, we rely on $base_dir/$configfile to set
# host_triplet and target_triplet.
#
load_file $base_dir/$configfile
#
# If objdir didn't get set in $base_dir/$configfile, set it to $base_dir.
# Make sure we source $objdir/$configfile in case $base_dir/$configfile doesn't
# exist and objdir was given on the command line.
#
if {[expr {[string match "." $objdir] || [string match $srcdir $objdir]}]} {
set objdir $base_dir
} else {
load_file $objdir/$configfile
}
# Well, this just demonstrates the real problem...
if {![info exists tool_root_dir]} {
set tool_root_dir [file dirname $objdir]
if {[file exists [file join $tool_root_dir testsuite]]} {
set tool_root_dir [file dirname $tool_root_dir]
}
}
verbose "Using test sources in $srcdir"
verbose "Using test binaries in $objdir"
verbose "Tool root directory is $tool_root_dir"
set execpath [file dirname $argv0]
set libdir [file dirname $execpath]/dejagnu
if {[info exists env(DEJAGNULIBS)]} {
set libdir $env(DEJAGNULIBS)
}
# list of extra search directories used by load_lib to look for libs
set libdirs {}
verbose "Using $libdir to find libraries"
#
# If the host or target was given on the command line, override the above
# config files. We allow $DEJAGNU to massage them though in case it would
# ever want to do such a thing.
#
if { $arg_host_triplet != "" } {
set host_triplet $arg_host_triplet
}
if { $arg_build_triplet != "" } {
set build_triplet $arg_build_triplet
}
# If we only specify --host, then that must be the build machine too,
# and we're stuck using the old functionality of a simple cross test.
if {[expr { $build_triplet == "" && $host_triplet != "" } ]} {
set build_triplet $host_triplet
}
# If we only specify --build, then we'll use that as the host too.
if {[expr { $build_triplet != "" && $host_triplet == "" } ]} {
set host_triplet $build_triplet
}
unset arg_host_triplet arg_build_triplet
#
# If the build machine type hasn't been specified by now, use config.guess.
#
if {[expr {$build_triplet == "" && $host_triplet == ""}]} {
# find config.guess
foreach dir "$libdir $libdir/libexec $libdir/.. $execpath $srcdir $srcdir/.. $srcdir/../.." {
verbose "Looking for ${dir}/config.guess" 2
if {[file exists [file join ${dir} config.guess]]} {
set config_guess [file join ${dir} config.guess]
verbose "Found [file join ${dir} config.guess]"
break
}
}
# get the canonical triplet
if {![info exists config_guess]} {
send_error "ERROR: Couldn't find config.guess program.\n"
exit 1
}
catch "exec $config_guess" build_triplet
switch -- $build_triplet {
"No uname command or uname output not recognized" -
"Unable to guess system type" {
verbose "WARNING: Uname output not recognized"
set build_triplet unknown
}
}
verbose "Assuming build host is $build_triplet"
if { $host_triplet == "" } {
set host_triplet $build_triplet
}
}
#
# Figure out the target. If the target hasn't been specified, then we have to
# assume we are native.
#
if { $arg_target_triplet != "" } {
set target_triplet $arg_target_triplet
} elseif { $target_triplet == "" } {
set target_triplet $build_triplet
verbose "Assuming native target is $target_triplet" 2
}
unset arg_target_triplet
#
# Default target_alias to target_triplet.
#
if {![info exists target_alias]} {
set target_alias $target_triplet
}
proc get_local_hostname { } {
if {[catch "info hostname" hb]} {
set hb ""
} else {
regsub "\\..*$" $hb "" hb
}
verbose "hostname=$hb" 3
return $hb
}
#
# We put these here so that they can be overridden later by site.exp or
# friends.
#
# Set up the target as machine NAME. We also load base-config.exp as a
# default configuration. The config files are sourced with the global
# variable $board set to the name of the current target being defined.
#
proc setup_target_hook { whole_name name } {
global board
global host_board
if {[info exists host_board]} {
set hb $host_board
} else {
set hb [get_local_hostname]
}
set board $whole_name
global board_type
set board_type "target"
load_config base-config.exp
if {![load_board_description ${name} ${whole_name} ${hb}]} {
if { $name != "unix" } {
perror "couldn't load description file for ${name}"
exit 1
} else {
load_generic_config "unix"
}
}
if {[board_info $board exists generic_name]} {
load_tool_target_config [board_info $board generic_name]
}
unset board
unset board_type
push_target $whole_name
if { [info procs ${whole_name}_init] != "" } {
${whole_name}_init $whole_name
}
if { ![isnative] && ![is_remote target] } {
global env build_triplet target_triplet
if { (![info exists env(DEJAGNU)]) && ($build_triplet != $target_triplet) } {
warning "Assuming target board is the local machine (which is probably wrong).\nYou may need to set your DEJAGNU environment variable."
}
}
}
#
# Clean things up afterwards.
#
proc cleanup_target_hook { name } {
global tool
# Clean up the target board.
if { [info procs "${name}_exit"] != "" } {
${name}_exit
}
# We also call the tool exit routine here.
if {[info exists tool]} {
if { [info procs "${tool}_exit"] != "" } {
${tool}_exit
}
}
remote_close target
pop_target
}
proc setup_host_hook { name } {
global board
global board_info
global board_type
set board $name
set board_type "host"
load_board_description $name
unset board
unset board_type
push_host $name
if { [info procs ${name}_init] != "" } {
${name}_init $name
}
}
proc setup_build_hook { name } {
global board
global board_info
global board_type
set board $name
set board_type "build"
load_board_description $name
unset board
unset board_type
push_build $name
if { [info procs ${name}_init] != "" } {
${name}_init $name
}
}
#
# Find and load the global config file if it exists.
# The global config file is used to set the connect mode and other
# parameters specific to each particular target.
# These files assume the host and target have been set.
#
if { [load_file -- $libdir/$configfile] == 0 } {
# If $DEJAGNU isn't set either then there isn't any global config file.
# Warn the user as there really should be one.
if { ! [info exists env(DEJAGNU)] } {
send_error "WARNING: Couldn't find the global config file.\n"
}
}
if {[info exists env(DEJAGNU)]} {
if { [load_file -- $env(DEJAGNU)] == 0 } {
# It may seem odd to only issue a warning if there isn't a global
# config file, but issue an error if $DEJAGNU is erroneously defined.
# Since $DEJAGNU is set there is *supposed* to be a global config file,
# so the current behaviour seems reasonable.
send_error "WARNING: global config file $env(DEJAGNU) not found.\n"
}
if {![info exists boards_dir]} {
set boards_dir "[file dirname $env(DEJAGNU)]/boards"
}
}
# Load user .dejagnurc file last as the ultimate override.
load_file ~/.dejagnurc
if {![info exists boards_dir]} {
set boards_dir ""
}
#
# parse out the config parts of the triplet name
#
# build values
if { $build_cpu == "" } {
regsub -- "-.*-.*" ${build_triplet} "" build_cpu
}
if { $build_vendor == "" } {
regsub -- "^\[a-z0-9\]*-" ${build_triplet} "" build_vendor
regsub -- "-.*" ${build_vendor} "" build_vendor
}
if { $build_os == "" } {
regsub -- ".*-.*-" ${build_triplet} "" build_os
}
# host values
if { $host_cpu == "" } {
regsub -- "-.*-.*" ${host_triplet} "" host_cpu
}
if { $host_vendor == "" } {
regsub -- "^\[a-z0-9\]*-" ${host_triplet} "" host_vendor
regsub -- "-.*" ${host_vendor} "" host_vendor
}
if { $host_os == "" } {
regsub -- ".*-.*-" ${host_triplet} "" host_os
}
# target values
if { $target_cpu == "" } {
regsub -- "-.*-.*" ${target_triplet} "" target_cpu
}
if { $target_vendor == "" } {
regsub -- "^\[a-z0-9\]*-" ${target_triplet} "" target_vendor
regsub -- "-.*" ${target_vendor} "" target_vendor
}
if { $target_os == "" } {
regsub -- ".*-.*-" ${target_triplet} "" target_os
}
#
# Load the primary tool initialization file.
#
proc load_tool_init { file } {
global srcdir
global loaded_libs
if {[info exists loaded_libs($file)]} {
return
}
set loaded_libs($file) ""
if {[file exists [file join ${srcdir} lib $file]]} {
verbose "Loading library file ${srcdir}/lib/$file"
if { [catch "uplevel #0 source ${srcdir}/lib/$file"] == 1 } {
send_error "ERROR: tcl error sourcing library file ${srcdir}/lib/$file.\n"
global errorInfo
if {[info exists errorInfo]} {
send_error "$errorInfo\n"
}
exit 1
}
} else {
warning "Couldn't find tool init file"
}
}
#
# load the testing framework libraries
#
load_lib utils.exp
load_lib framework.exp
load_lib debugger.exp
load_lib remote.exp
load_lib target.exp
load_lib targetdb.exp
load_lib libgloss.exp
# Initialize the test counters and reset them to 0.
init_testcounts
reset_vars
#
# Parse the command line arguments.
#
# Load the tool initialization file. Allow the --tool option to override
# what's set in the site.exp file.
if {[info exists comm_line_tool]} {
set tool $comm_line_tool
}
if {[info exists tool]} {
load_tool_init ${tool}.exp
}
set argc [ llength $argv ]
for { set i 0 } { $i < $argc } { incr i } {
set option [ lindex $argv $i ]
# make all options have two hyphens
switch -glob -- $option {
"--*" {
}
"-*" {
set option "-$option"
}
}
# split out the argument for options that take them
switch -glob -- $option {
"--*=*" {
regexp {^[^=]*=(.*)$} $option nil optarg
}
"--bu*" -
"--ho*" -
"--ig*" -
"--m*" -
"--n*" -
"--ob*" -
"--ou*" -
"--sr*" -
"--str*" -
"--ta*" -
"--di*" -
"--to*" {
incr i
set optarg [lindex $argv $i]
}
}
switch -glob -- $option {
"--V*" -
"--vers*" { # (--version) version numbers
send_user "DejaGnu version\t$frame_version\n"
send_user "Expect version\t[exp_version]\n"
send_user "Tcl version\t[ info tclversion ]\n"
exit 0
}
"--v*" { # (--verbose) verbose output
# Already parsed.
continue
}
"--bu*" { # (--build) the build host configuration
# Already parsed (and don't set again). Let $DEJAGNU rename it.
continue
}
"--ho*" { # (--host) the host configuration
# Already parsed (and don't set again). Let $DEJAGNU rename it.
continue
}
"--target_bo*" {
# Set it again, father knows best.
set target_list $optarg
continue
}
"--ta*" { # (--target) the target configuration
# Already parsed (and don't set again). Let $DEJAGNU rename it.
continue
}
"--a*" { # (--all) print all test output to screen
set all_flag 1
verbose "Print all test output to screen"
continue
}
"--di*" {
# Already parsed (and don't set again). Let $DEJAGNU rename it.
continue
}
"--de*" { # (--debug) expect internal debugging
if {[file exists ./dbg.log]} {
catch [file delete -force -- dbg.log]
}
if { $verbose > 2 } {
exp_internal -f dbg.log 1
} else {
exp_internal -f dbg.log 0
}
verbose "Expect Debugging is ON"
continue
}
"--D[01]" { # (-Debug) turn on Tcl debugger
# The runtest shell script handles this option, but it
# still appears in the options in the Tcl code.
verbose "Tcl debugger is ON"
continue
}
"--m*" { # (--mail) mail the output
set mailing_list $optarg
set mail_logs 1
verbose "Mail results to $mailing_list"
continue
}
"--r*" { # (--reboot) reboot the target
set reboot 1
verbose "Will reboot the target (if supported)"
continue
}
"--ob*" { # (--objdir) where the test case object code lives
# Already parsed, but parse again to make sure command line
# options override any config file.
set objdir $optarg
verbose "Using test binaries in $objdir"
continue
}
"--ou*" { # (--outdir) where to put the output files
set outdir $optarg
verbose "Test output put in $outdir"
continue
}
"--log_dialog*" {
incr log_dialog
continue
}
"*.exp" { # specify test names to run
set all_runtests($option) ""
verbose "Running only tests $option"
continue
}
"*.exp=*" { # specify test names to run
set tmp [split $option "="]
set all_runtests([lindex $tmp 0]) [lindex $tmp 1]
verbose "Running only tests $option"
unset tmp
continue
}
"--ig*" { # (--ignore) specify test names to exclude
set ignoretests $optarg
verbose "Ignoring test $ignoretests"
continue
}
"--sr*" { # (--srcdir) where the testsuite source code lives
# Already parsed, but parse again to make sure command line
# options override any config file.
set srcdir $optarg
continue
}
"--str*" { # (--strace) expect trace level
set tracelevel $optarg
strace $tracelevel
verbose "Source Trace level is now $tracelevel"
continue
}
"--sta*" { # (--status) exit status flag
# preserved for compatability, do nothing
continue
}
"--tool_opt*" {
continue
}
"--tool_exec*" {
set TOOL_EXECUTABLE $optarg
continue
}
"--to*" { # (--tool) specify tool name
set tool $optarg
verbose "Testing $tool"
continue
}
"--x*" {
set xml_file_name $optarg
set xml 1
verbose "XML logging turned on"
continue
}
"--he*" { # (--help) help text
usage
exit 0
}
"[A-Z0-9_-.]*=*" { # skip makefile style args like CC=gcc, etc... (processed in first pass)
continue
}
default {
if {[info exists tool]} {
if { [info procs ${tool}_option_proc] != "" } {
if {[${tool}_option_proc $option]} {
continue
}
}
}
send_error "\nIllegal Argument \"$option\"\n"
send_error "try \"runtest --help\" for option list\n"
exit 1
}
}
}
#
# check for a few crucial variables
#
if {![info exists tool]} {
send_error "WARNING: No tool specified\n"
set tool ""
}
#
# initialize a few Tcl variables to something other than their default
#
if { $verbose > 2 || $log_dialog } {
log_user 1
} else {
log_user 0
}
set timeout 10
#
# open log files
#
open_logs
# print the config info
clone_output "Test run by $logname on [timestamp -format %c]"
if {[is3way]} {
clone_output "Target is $target_triplet"
clone_output "Host is $host_triplet"
clone_output "Build is $build_triplet"
} else {
if {[isnative]} {
clone_output "Native configuration is $target_triplet"
} else {
clone_output "Target is $target_triplet"
clone_output "Host is $host_triplet"
}
}
clone_output "\n\t\t=== $tool tests ===\n"
#
# Look for the generic board configuration file. It searches in several
# places: ${libdir}/config, ${libdir}/../config, and $boards_dir.
#
proc load_generic_config { name } {
global srcdir
global configfile
global libdir
global env
global board
global board_info
global boards_dir
global board_type
if {[info exists board]} {
if {![info exists board_info($board,generic_name)]} {
set board_info($board,generic_name) $name
}
}
if {[info exists board_type]} {
set type "for $board_type"
} else {
set type ""
}
set dirlist [concat ${libdir}/config [file dirname $libdir]/config $boards_dir]
set result [search_and_load_file "generic interface file $type" ${name}.exp $dirlist]
return $result
}
#
# Load the tool-specific target description.
#
proc load_config { args } {
global srcdir
global board_type
set found 0
return [search_and_load_file "tool-and-target-specific interface file" $args [list ${srcdir}/config ${srcdir}/../config ${srcdir}/../../config ${srcdir}/../../../config]]
}
#
# Find the files that set up the configuration for the target. There
# are assumed to be two of them; one defines a basic set of
# functionality for the target that can be used by all tool
# testsuites, and the other defines any necessary tool-specific
# functionality. These files are loaded via load_config.
#
# These used to all be named $target_abbrev-$tool.exp, but as the
# $tool variable goes away, it's now just $target_abbrev.exp. First
# we look for a file named with both the abbrev and the tool names.
# Then we look for one named with just the abbrev name. Finally, we
# look for a file called default, which is the default actions, as
# some tools could be purely host based. Unknown is mostly for error
# trapping.
#
proc load_tool_target_config { name } {
global target_os libdir srcdir
set found [load_config "${name}.exp" "${target_os}.exp" "default.exp" "unknown.exp"]
if { $found == 0 } {
send_error "WARNING: Couldn't find tool config file for $name, using default.\n"
# If we can't load the tool init file, this must be a simple natively hosted
# test suite, so we use the default procs for Unix.
if { [search_and_load_file "library file" default.exp [list $libdir $libdir/config [file dirname [file dirname $srcdir]]/dejagnu/config $srcdir/config . [file dirname [file dirname [file dirname $srcdir]]]/dejagnu/config]] == 0 } {
send_error "ERROR: Couldn't find default tool init file.\n"
exit 1
}
}
}
#
# Find the file that describes the machine specified by board_name.
#
proc load_board_description { board_name args } {
global srcdir
global configfile
global libdir
global env
global board
global board_info
global boards_dir
global board_type
set dejagnu ""
if { [llength $args] > 0 } {
set whole_name [lindex $args 0]
} else {
set whole_name $board_name
}
set board_info($whole_name,name) $whole_name
if {![info exists board]} {
set board $whole_name
set board_set 1
} else {
set board_set 0
}
set dirlist {}
if { [llength $args] > 1 } {
set suffix [lindex $args 1]
if { ${suffix} != "" } {
foreach x ${boards_dir} {
lappend dirlist ${x}/${suffix}
}
lappend dirlist ${libdir}/baseboards/${suffix}
}
}
set dirlist [concat $dirlist $boards_dir]
lappend dirlist ${libdir}/baseboards
verbose "dirlist is $dirlist"
if {[info exists board_type]} {
set type "for $board_type"
} else {
set type ""
}
if {![info exists board_info($whole_name,isremote)]} {
set board_info($whole_name,isremote) 1
if {[info exists board_type]} {
if { $board_type == "build" } {
set board_info($whole_name,isremote) 0
}
}
if { ${board_name} == [get_local_hostname] } {
set board_info($whole_name,isremote) 0
}
}
search_and_load_file "standard board description file $type" standard.exp $dirlist
set found [search_and_load_file "board description file $type" ${board_name}.exp $dirlist]
if { $board_set != 0 } {
unset board
}
return $found
}
#
# Find the base-level file that describes the machine specified by args. We
# only look in one directory, ${libdir}/baseboards.
#
proc load_base_board_description { board_name } {
global srcdir
global configfile
global libdir
global env
global board
global board_info
global board_type
set board_set 0
set board_info($board_name,name) $board_name
if {![info exists board]} {
set board $board_name
set board_set 1
}
if {[info exists board_type]} {
set type "for $board_type"
} else {
set type ""
}
if {![info exists board_info($board_name,isremote)]} {
set board_info($board_name,isremote) 1
if {[info exists board_type]} {
if { $board_type == "build" } {
set board_info($board_name,isremote) 0
}
}
}
if { ${board_name} == [get_local_hostname] } {
set board_info($board_name,isremote) 0
}
set found [search_and_load_file "board description file $type" ${board_name}.exp ${libdir}/baseboards]
if { $board_set != 0 } {
unset board
}
return $found
}
#
# Source the testcase in TEST_FILE_NAME.
#
proc runtest { test_file_name } {
global prms_id
global bug_id
global test_result
global errcnt
global errorInfo
global tool
clone_output "Running $test_file_name ..."
set prms_id 0
set bug_id 0
set test_result ""
if {[file exists $test_file_name]} {
set timestart [timestamp]
if {[info exists tool]} {
if { [info procs "${tool}_init"] != "" } {
${tool}_init $test_file_name
}
}
if { [catch "uplevel #0 source $test_file_name"] == 1 } {
# If we have a Tcl error, propagate the exit status so
# that 'make' (if it invokes runtest) notices the error.
global exit_status exit_error
# exit error is set by the --status command line option
if { $exit_status == 0 } {
set exit_status 2
}
# We can't call `perror' here, it resets `errorInfo'
# before we want to look at it. Also remember that perror
# increments `errcnt'. If we do call perror we'd have to
# reset errcnt afterwards.
clone_output "ERROR: tcl error sourcing $test_file_name."
if {[info exists errorInfo]} {
clone_output "ERROR: $errorInfo"
unset errorInfo
}
}
if {[info exists tool]} {
if { [info procs "${tool}_finish"] != "" } {
${tool}_finish
}
}
set timeend [timestamp]
set timediff [expr {$timeend - $timestart}]
verbose -log "testcase $test_file_name completed in $timediff seconds" 4
} else {
# This should never happen, but maybe if the file got removed
# between the `find' above and here.
perror "$test_file_name does not exist." 0
}
}
# Trap some signals so we know what's happening. These replace the previous
# ones because we've now loaded the library stuff.
#
if {![exp_debug]} {
foreach sig {{SIGINT {interrupted by user} 130} \
{SIGQUIT {interrupted by user} 131} \
{SIGTERM {terminated} 143}} {
set signal [lindex $sig 0]
set str [lindex $sig 1]
set code [lindex $sig 2]
trap "send_error \"got a \[trap -name\] signal, $str \\n\"; set exit_status $code; log_and_exit;" $signal
verbose "setting trap for $signal to $str" 1
}
unset signal str sig
}
#
# Given a list of targets, process any iterative lists.
#
proc process_target_variants { target_list } {
set result {}
foreach x $target_list {
if {[regexp "\\(" $x]} {
regsub "^.*\\((\[^()\]*)\\)$" "$x" "\\1" variant_list
regsub "\\(\[^(\]*$" "$x" "" x
set list [process_target_variants $x]
set result {}
foreach x $list {
set result [concat $result [iterate_target_variants $x [split $variant_list ","]]]
}
} elseif {[regexp "\{" $x]} {
regsub "^.*\{(\[^\{\}\]*)\}$" "$x" "\\1" variant_list
regsub "\{\[^\{\]*$" "$x" "" x
set list [process_target_variants $x]
foreach x $list {
foreach i [split $variant_list ","] {
set name $x
if { $i != "" } {
append name "/" $i
}
lappend result $name
}
}
} else {
lappend result "$x"
}
}
return $result
}
proc iterate_target_variants { target variants } {
return [iterate_target_variants_two $target $target $variants]
}
#
# Given a list of variants, produce the list of all possible combinations.
#
proc iterate_target_variants_two { orig_target target variants } {
if { [llength $variants] == 0 } {
return [list $target]
} else {
if { [llength $variants] > 1 } {
set result [iterate_target_variants_two $orig_target $target [lrange $variants 1 end]]
} else {
if { $target != $orig_target } {
set result [list $target]
} else {
set result {}
}
}
if { [lindex $variants 0] != "" } {
append target "/" [lindex $variants 0]
return [concat $result [iterate_target_variants_two $orig_target $target [lrange $variants 1 end]]]
} else {
return [concat $result $target]
}
}
}
setup_build_hook [get_local_hostname]
if {[info exists host_board]} {
setup_host_hook $host_board
} else {
set hb [get_local_hostname]
if { $hb != "" } {
setup_host_hook $hb
}
}
#
# main test execution loop
#
if {[info exists errorInfo]} {
unset errorInfo
}
# make sure we have only single path delimiters
regsub -all "\(\[^/\]\)//*" $srcdir "\\1/" srcdir
if {![info exists target_list]} {
# Make sure there is at least one target machine. It's probably a Unix box,
# but that's just a guess.
set target_list { "unix" }
} else {
verbose "target list is $target_list"
}
#
# Iterate through the list of targets.
#
global current_target
set target_list [process_target_variants $target_list]
set target_count [llength $target_list]
clone_output "Schedule of variations:"
foreach current_target $target_list {
clone_output " $current_target"
}
clone_output ""
foreach current_target $target_list {
verbose "target is $current_target"
set current_target_name $current_target
set tlist [split $current_target /]
set current_target [lindex $tlist 0]
set board_variant_list [lrange $tlist 1 end]
# Set the counts for this target to 0.
reset_vars
clone_output "Running target $current_target_name"
setup_target_hook $current_target_name $current_target
# If multiple passes requested, set them up. Otherwise prepare just one.
# The format of `MULTIPASS' is a list of elements containing
# "{ name var1=value1 ... }" where `name' is a generic name for the pass and
# currently has no other meaning.
global env
if { [info exists MULTIPASS] } {
set multipass $MULTIPASS
}
if { $multipass == "" } {
set multipass { "" }
}
# If PASS is specified, we want to run only the tests specified.
# Its value should be a number or a list of numbers that specify
# the passes that we want to run.
if {[info exists PASS]} {
set pass $PASS
} else {
set pass ""
}
if {$pass != ""} {
set passes [list]
foreach p $pass {
foreach multipass_elem $multipass {
set multipass_name [lindex $multipass_elem 0]
if {$p == $multipass_name} {
lappend passes $multipass_elem
break
}
}
}
set multipass $passes
}
foreach pass $multipass {
# multipass_name is set for `record_test' to use (see framework.exp).
if { [lindex $pass 0] != "" } {
set multipass_name [lindex $pass 0]
clone_output "Running pass `$multipass_name' ..."
} else {
set multipass_name ""
}
set restore ""
foreach varval [lrange $pass 1 end] {
set tmp [string first "=" $varval]
set var [string range $varval 0 [expr {$tmp - 1}]]
# Save previous value.
if {[info exists $var]} {
lappend restore "$var [list [eval concat \$$var]]"
} else {
lappend restore "$var"
}
# Handle "CFLAGS=$CFLAGS foo".
eval set $var \[string range \"$varval\" [expr {$tmp + 1}] end\]
verbose "$var is now [eval concat \$$var]"
unset tmp var
}
# look for the top level testsuites. if $tool doesn't
# exist and there are no subdirectories in $srcdir, then
# we default to srcdir.
set test_top_dirs [lsort [getdirs -all ${srcdir} "${tool}*"]]
if { ${test_top_dirs} == "" } {
set test_top_dirs ${srcdir}
} else {
# JYG:
# DejaGNU's notion of test tree and test files is very
# general:
# given ${srcdir} and ${tool}, any subdirectory (at any
# level deep) with the "${tool}" prefix starts a test tree
# given a test tree, any *.exp file underneath (at any
# level deep) is a test file.
#
# For test tree layouts with ${tool} prefix on
# both a parent and a child directory, we need to eliminate
# the child directory entry from test_top_dirs list.
# e.g. gdb.hp/gdb.base-hp/ would result in two entries
# in the list: gdb.hp, gdb.hp/gdb.base-hp.
# If the latter not eliminated, test files under
# gdb.hp/gdb.base-hp would be run twice (since test files
# are gathered from all sub-directories underneath a
# directory).
#
# Since ${tool} may be g++, etc. which could confuse
# regexp, we cannot do the simpler test:
# ...
# if [regexp "${srcdir}/.*${tool}.*/.*${tool}.*" ${dir}]
# ...
# instead, we rely on the fact that test_top_dirs is
# a sorted list of entries, and any entry that contains
# the previous valid test top dir entry in its own pathname
# must be excluded.
set temp_top_dirs ""
set prev_dir ""
foreach dir "${test_top_dirs}" {
if { [string length ${prev_dir}] == 0 ||
[string first "${prev_dir}/" ${dir}] == -1} {
# the first top dir entry, or an entry that
# does not share the previous entry's entire
# pathname, record it as a valid top dir entry.
#
lappend temp_top_dirs ${dir}
set prev_dir ${dir}
}
}
set test_top_dirs ${temp_top_dirs}
}
verbose "Top level testsuite dirs are ${test_top_dirs}" 2
set testlist ""
if {[array exists all_runtests]} {
foreach x [array names all_runtests] {
verbose "trying to glob ${srcdir}/${x}" 2
set s [glob -nocomplain ${srcdir}/$x]
if { $s != "" } {
set testlist [concat $testlist $s]
}
}
}
#
# If we have a list of tests, run all of them.
#
if { $testlist != "" } {
foreach test_name $testlist {
if { ${ignoretests} != "" } {
if { 0 <= [lsearch ${ignoretests} [file tail ${test_name}]]} {
continue
}
}
# set subdir to the tail of the dirname after $srcdir,
# for the driver files that want it. XXX this is silly.
# drivers should get a single var, not "$srcdir/$subdir"
set subdir [file dirname $test_name]
set p [expr {[string length $srcdir] - 1}]
while {0 < $p && [string index $srcdir $p] == "/"} {
incr p -1
}
if {[string range $subdir 0 $p] == $srcdir} {
set subdir [string range $subdir [expr {$p + 1}] end]
regsub "^/" $subdir "" subdir
}
# XXX not the right thing to do.
set runtests [list [file tail $test_name] ""]
runtest $test_name
}
} else {
#
# Go digging for tests.
#
foreach dir "${test_top_dirs}" {
if { ${dir} != ${srcdir} } {
# Ignore this directory if is a directory to be
# ignored.
if {[info exists ignoredirs] && $ignoredirs != ""} {
set found 0
foreach directory $ignoredirs {
if {[string match "*${directory}*" $dir]} {
set found 1
break
}
}
if { $found } {
continue
}
}
# Run the test if dir_to_run was specified as a
# value (for example in MULTIPASS) and the test
# directory matches that directory.
if {[info exists dir_to_run] && $dir_to_run != ""} {
# JYG: dir_to_run might be a space delimited list
# of directories. Look for match on each item.
set found 0
foreach directory $dir_to_run {
if {[string match "*${directory}*" $dir]} {
set found 1
break
}
}
if {!$found} {
continue
}
}
# Run the test if cmdline_dir_to_run was specified
# by the user using --directory and the test
# directory matches that directory
if {[info exists cmdline_dir_to_run] \
&& $cmdline_dir_to_run != ""} {
# JYG: cmdline_dir_to_run might be a space delimited
# list of directories. Look for match on each item.
set found 0
foreach directory $cmdline_dir_to_run {
if {[string match $directory $dir]} {
set found 1
break
}
}
if {!$found} {
continue
}
}
foreach test_name [lsort [find ${dir} *.exp]] {
if { ${test_name} == "" } {
continue
}
# Ignore this one if asked to.
if { ${ignoretests} != "" } {
if { 0 <= [lsearch ${ignoretests} [file tail ${test_name}]]} {
continue
}
}
# Get the path after the $srcdir so we know
# the subdir we're in.
set subdir [file dirname $test_name]
# We used to do
# regsub $srcdir [file dirname $test_name] "" subdir
# but what if [file dirname $test_name] contains regexp
# characters? We lose. Instead...
set first [string first $srcdir $subdir]
if { $first >= 0 } {
set first [expr {$first + [string length $srcdir]}]
set subdir [string range $subdir $first end]
regsub "^/" "$subdir" "" subdir
}
if { "$srcdir" == "$subdir" || "$srcdir" == "$subdir/" } {
set subdir ""
}
# Check to see if the range of tests is limited,
# set `runtests' to a list of two elements: the script name
# and any arguments ("" if none).
if {[array exists all_runtests]} {
verbose "searching for $test_name in [array names all_runtests]" 2
if { 0 > [lsearch [array names all_runtests] [file tail $test_name]]} {
if { 0 > [lsearch [array names all_runtests] $test_name] } {
continue
}
}
set runtests [list [file tail $test_name] $all_runtests([file tail $test_name])]
} else {
set runtests [list [file tail $test_name] ""]
}
runtest $test_name
}
}
}
# Restore the variables set by this pass.
foreach varval $restore {
if { [llength $varval] > 1 } {
verbose "Restoring [lindex $varval 0] to [lindex $varval 1]" 4
set [lindex $varval 0] [lindex $varval 1]
} else {
verbose "Restoring [lindex $varval 0] to `unset'" 4
unset -- [lindex $varval 0]
}
}
}
}
cleanup_target_hook $current_target
if { $target_count > 1 } {
log_summary
}
}
log_and_exit
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化