Update version numbers for 1.6.3 release branch
[dejagnu.git] / runtest.exp
blob7cff4e6ac9928bac71ba8834d98d5cb42de1e5e8
1 # runtest.exp -- Test framework driver
2 # Copyright (C) 1992-2019, 2020 Free Software Foundation, Inc.
4 # This file is part of DejaGnu.
6 # DejaGnu is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # DejaGnu is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with DejaGnu; if not, write to the Free Software Foundation,
18 # Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
20 # This file was written by Rob Savoye <rob@welcomehome.org>.
22 set frame_version 1.6.3-rc1
23 if {![info exists argv0]} {
24 send_error "Must use a version of Expect greater than 5.0\n"
25 exit 1
28 # trap some signals so we know whats happening. These definitions are only
29 # temporary until we read in the library stuff
31 trap { send_user "\ninterrupted by user\n"; exit 130 } SIGINT
32 trap { send_user "\nquit\n"; exit 131 } SIGQUIT
33 trap { send_user "\nterminated\n"; exit 143 } SIGTERM
36 # Initialize a few global variables used by all tests.
37 # `reset_vars' resets several of these, we define them here to document their
38 # existence. In fact, it would be nice if all globals used by some interface
39 # of dejagnu proper were documented here.
41 # Keep these all lowercase. Interface variables used by the various
42 # testsuites (eg: the gcc testsuite) should be in all capitals
43 # (eg: TORTURE_OPTIONS).
45 set mail_logs 0 ;# flag for mailing of summary and diff logs
46 set psum_file "latest" ;# file name of previous summary to diff against
48 set exit_status 0 ;# exit code returned by this program
50 set xfail_flag 0 ;# indicates that a failure is expected
51 set xfail_prms 0 ;# GNATS prms id number for this expected failure
52 set kfail_flag 0 ;# indicates that it is a known failure
53 set kfail_prms 0 ;# bug id for the description of the known failure
54 set sum_file "" ;# name of the file that contains the summary log
55 set base_dir "" ;# the current working directory
56 set xml_file "" ;# handle on the XML file if requested
57 set xml 0 ;# flag for requesting xml
58 set logname "" ;# the users login name
59 set prms_id 0 ;# GNATS prms id number
60 set bug_id 0 ;# optional bug id number
61 set dir "" ;# temp variable for directory names
62 set srcdir "." ;# source directory containing the test suite
63 set ignoretests "" ;# list of tests to not execute
64 set objdir "." ;# directory where test case binaries live
65 set reboot 0
66 set multipass "" ;# list of passes and var settings
67 set errno ""; ;#
68 set exit_error 1 ;# Toggle for whether to set the exit status
69 ;# on Tcl bugs in test case drivers.
71 # These describe the host and target environments.
73 set build_triplet "" ;# type of architecture to run tests on
74 set build_os "" ;# type of os the tests are running on
75 set build_vendor "" ;# vendor name of the OS or workstation the test are running on
76 set build_cpu "" ;# type of the cpu tests are running on
77 set host_triplet "" ;# type of architecture to run tests on, sometimes remotely
78 set host_os "" ;# type of os the tests are running on
79 set host_vendor "" ;# vendor name of the OS or workstation the test are running on
80 set host_cpu "" ;# type of the cpu tests are running on
81 set target_triplet "" ;# type of architecture to run tests on, final remote
82 set target_os "" ;# type of os the tests are running on
83 set target_vendor "" ;# vendor name of the OS or workstation the test are running on
84 set target_cpu "" ;# type of the cpu tests are running on
85 set target_alias "" ;# standard abbreviation of target
86 set compiler_flags "" ;# the flags used by the compiler
89 # These set configuration file names and are local to this file.
91 set local_init_file site.exp ;# testsuite-local init file name
92 set global_init_file site.exp ;# global init file name
95 # These are used to locate parts of the testsuite.
97 set testsuitedir "testsuite" ;# top-level testsuite source directory
98 set testbuilddir "testsuite" ;# top-level testsuite object directory
101 # Collected errors
103 namespace eval ::dejagnu::error {
104 # list of { file message errorCode errorInfo } lists
105 variable list [list]
108 # Various ccache versions provide incorrect debug info such as ignoring
109 # different current directory, breaking GDB testsuite.
110 set env(CCACHE_DISABLE) 1
111 unset -nocomplain env(CCACHE_NODISABLE)
114 # some convenience abbreviations
116 set hex "0x\[0-9A-Fa-f\]+"
117 set decimal "\[0-9\]+"
120 # set the base dir (current working directory)
122 set base_dir [pwd]
125 # These are set here instead of the init module so they can be overridden
126 # by command line options.
128 set all_flag 0
129 set binpath ""
130 set debug 0
131 set options ""
132 set outdir "."
133 set reboot 1
134 set tracelevel 0
135 set verbose 0
136 set log_dialog 0
139 # verbose [-n] [-log] [--] message [level]
141 # Print MESSAGE if the verbose level is >= LEVEL.
142 # The default value of LEVEL is 1.
143 # "-n" says to not print a trailing newline.
144 # "-log" says to add the text to the log file even if it won't be printed.
145 # Note that the apparent behaviour of `send_user' dictates that if the message
146 # is printed it is also added to the log file.
147 # Use "--" if MESSAGE begins with "-".
149 # This is defined here rather than in framework.exp so we can use it
150 # while still loading in the support files.
152 proc verbose { args } {
153 global verbose
154 set newline 1
155 set logfile 0
157 set i 0
158 if { [string index [lindex $args 0] 0] eq "-" } {
159 for { set i 0 } { $i < [llength $args] } { incr i } {
160 if { [lindex $args $i] eq "--" } {
161 incr i
162 break
163 } elseif { [lindex $args $i] eq "-n" } {
164 set newline 0
165 } elseif { [lindex $args $i] eq "-log" } {
166 set logfile 1
167 } elseif { [lindex $args $i] eq "-x" } {
168 set xml 1
169 } elseif { [string index [lindex $args $i] 0] eq "-" } {
170 clone_output "ERROR: verbose: illegal argument: [lindex $args $i]"
171 return
172 } else {
173 break
176 if { [llength $args] == $i } {
177 clone_output "ERROR: verbose: nothing to print"
178 return
182 set level 1
183 if { [llength $args] > $i + 1 } {
184 set level [lindex $args [expr { $i + 1 }]]
186 set message [lindex $args $i]
188 if { $verbose >= $level } {
189 # We assume send_user also sends the text to the log file (which
190 # appears to be the case though the docs aren't clear on this).
191 if { $newline } {
192 send_user -- "$message\n"
193 } else {
194 send_user -- $message
196 } elseif { $logfile } {
197 if { $newline } {
198 send_log -- "$message\n"
199 } else {
200 send_log -- $message
206 # Transform a tool name to get the installed name.
207 # target_triplet is the canonical target name. target_alias is the
208 # target name used when configure was run.
210 proc transform { name } {
211 global target_triplet
212 global target_alias
213 global host_triplet
214 global board
216 if { $target_triplet eq $host_triplet } {
217 return $name
219 if { $target_triplet eq "native" } {
220 return $name
222 if {[board_info host exists no_transform_name]} {
223 return $name
225 if { $target_triplet eq "" } {
226 return $name
227 } else {
228 if {[info exists board]} {
229 if {[board_info $board exists target_install]} {
230 set target_install [board_info $board target_install]
233 if {[target_info exists target_install]} {
234 set target_install [target_info target_install]
236 if {[info exists target_alias]} {
237 set tmp $target_alias-$name
238 } elseif {[info exists target_install]} {
239 if { [lsearch -exact $target_install $target_alias] >= 0 } {
240 set tmp $target_alias-$name
241 } else {
242 set tmp "[lindex $target_install 0]-$name"
245 verbose "Transforming $name to $tmp"
246 return $tmp
251 # findfile arg0 [arg1] [arg2]
253 # Find a file and see if it exists. If you only care about the false
254 # condition, then you'll need to pass a null "" for arg1.
255 # arg0 is the filename to look for. If the only arg,
256 # then that's what gets returned. If this is the
257 # only arg, then if it exists, arg0 gets returned.
258 # if it doesn't exist, return only the prog name.
259 # arg1 is optional, and it's what gets returned if
260 # the file exists.
261 # arg2 is optional, and it's what gets returned if
262 # the file doesn't exist.
264 proc findfile { args } {
265 # look for the file
266 verbose "Seeing if [lindex $args 0] exists." 2
267 if {[file exists [lindex $args 0]]} {
268 if { [llength $args] > 1 } {
269 verbose "Found file, returning [lindex $args 1]"
270 return [lindex $args 1]
271 } else {
272 verbose "Found file, returning [lindex $args 0]"
273 return [lindex $args 0]
275 } else {
276 if { [llength $args] > 2 } {
277 verbose "Didn't find file [lindex $args 0], returning [lindex $args 2]"
278 return [lindex $args 2]
279 } else {
280 verbose "Didn't find file, returning [file tail [lindex $args 0]]"
281 return [transform [file tail [lindex $args 0]]]
287 # load_file [-1] [--] file1 [ file2 ... ]
289 # Utility to source a file. All are sourced in order unless the flag "-1"
290 # is given in which case we stop after finding the first one.
291 # The result is 1 if a file was found, 0 if not.
292 # If a tcl error occurs while sourcing a file, we print an error message
293 # and exit.
295 proc load_file { args } {
296 set i 0
297 set only_one 0
298 if { [lindex $args $i] eq "-1" } {
299 set only_one 1
300 incr i
302 if { [lindex $args $i] eq "--" } {
303 incr i
306 set found 0
307 foreach file [lrange $args $i end] {
308 verbose "Looking for $file" 2
309 # In Tcl, "file exists" fails if the filename looks like
310 # ~/FILE and the environment variable HOME does not exist.
311 if {! [catch {file exists $file} result] && $result} {
312 set found 1
313 verbose "Found $file"
314 if { [catch "uplevel #0 source $file"] == 1 } {
315 send_error "ERROR: tcl error sourcing $file.\n"
316 global errorInfo
317 if {[info exists errorInfo]} {
318 send_error "$errorInfo\n"
320 exit 1
322 if { $only_one } {
323 break
327 return $found
331 # search_and_load_file -- search DIRLIST looking for FILELIST.
332 # TYPE is used when displaying error and progress messages.
334 proc search_and_load_file { type filelist dirlist } {
335 set found 0
337 foreach dir $dirlist {
338 foreach initfile $filelist {
339 set filename [file join $dir $initfile]
340 verbose "Looking for $type $filename" 2
341 if {[file exists $filename]} {
342 set found 1
343 set error ""
344 if { $type ne "library file" } {
345 send_user "Using $filename as $type.\n"
346 } else {
347 verbose "Loading $filename"
349 if {[catch "uplevel #0 source $filename" error] == 1} {
350 global errorInfo
351 send_error "ERROR: tcl error sourcing $type $filename.\n$error\n"
352 if {[info exists errorInfo]} {
353 send_error "$errorInfo\n"
355 exit 1
357 break
360 if { $found } {
361 break
364 return $found
368 # Give a usage statement.
370 proc usage { } {
371 global tool
373 send_user "USAGE: runtest \[options...\]\n"
374 send_user "\t--all, -a\t\tPrint all test output to screen\n"
375 send_user "\t--build \[triplet\]\tThe canonical triplet of the build machine\n"
376 send_user "\t--debug\t\t\tSet expect debugging ON\n"
377 send_user "\t--directory name\tRun only the tests in directory 'name'\n"
378 send_user "\t--global_init \[name\]\tThe file to load for global configuration\n"
379 send_user "\t--help\t\t\tPrint help text\n"
380 send_user "\t--host \[triplet\]\tThe canonical triplet of the host machine\n"
381 send_user "\t--host_board \[name\]\tThe host board to use\n"
382 send_user "\t--ignore \[name(s)\]\tThe names of specific tests to ignore\n"
383 send_user "\t--local_init \[name\]\tThe file to load for local configuration\n"
384 send_user "\t--log_dialog\t\t\Emit Expect output on stdout\n"
385 send_user "\t--mail \[name(s)\]\tWhom to mail the results to\n"
386 send_user "\t--objdir \[name\]\t\tThe test suite binary directory\n"
387 send_user "\t--outdir \[name\]\t\tThe directory to put logs in\n"
388 send_user "\t--reboot\t\tReboot the target (if supported)\n"
389 send_user "\t--srcdir \[name\]\t\tThe test suite source code directory\n"
390 send_user "\t--status\t\tSet the exit status to fail on Tcl errors\n"
391 send_user "\t--strace \[number\]\tTurn on Expect tracing\n"
392 send_user "\t--target \[triplet\]\tThe canonical triplet of the target board\n"
393 send_user "\t--target_board \[name(s)\] The list of target boards to run tests on\n"
394 send_user "\t--tool \[name(s)\]\tRun tests on these tools\n"
395 send_user "\t--tool_exec \[name\]\tThe path to the tool executable to test\n"
396 send_user "\t--tool_opts \[options\]\tA list of additional options to pass to the tool\n"
397 send_user "\t--verbose, -v\t\tProduce verbose output\n"
398 send_user "\t--version, -V\t\tPrint all relevant version numbers\n"
399 send_user "\t--xml, -x\t\tWrite out an XML results file\n"
400 send_user "\t--D\[0-1\]\t\tTcl debugger\n"
401 send_user "\tscript.exp\[=arg(s)\]\tRun these tests only\n"
402 if { [info exists tool] } {
403 if { [info procs ${tool}_option_help] ne "" } {
404 ${tool}_option_help
410 # Parse the arguments the first time looking for these. We will ultimately
411 # parse them twice. Things are complicated because:
412 # - we want to parse --verbose early on
413 # - we don't want config files to override command line arguments
414 # (eg: $base_dir/$local_init_file vs --host/--target)
415 # - we need some command line arguments before we can process some config files
416 # (eg: --objdir before $objdir/$local_init_file, --host/--target before $DEJAGNU)
417 # The use of `arg_host_triplet' and `arg_target_triplet' lets us avoid parsing
418 # the arguments three times.
421 namespace eval ::dejagnu::command_line {
422 variable cmd_var_list [list]
424 proc save_cmd_var {name} {
425 variable cmd_var_list
427 upvar 1 $name target_var
428 lappend cmd_var_list $name $target_var
431 proc restore_cmd_vars {} {
432 variable cmd_var_list
434 foreach {name value} $cmd_var_list {
435 uplevel 1 set $name $value
437 verbose "Variables set by command line arguments restored." 4
440 proc dump_cmd_vars {} {
441 variable cmd_var_list
443 verbose "Variables set by command line arguments:" 4
444 foreach {name value} $cmd_var_list {
445 verbose " $name -> $value" 4
450 set arg_host_triplet ""
451 set arg_target_triplet ""
452 set arg_build_triplet ""
453 set argc [ llength $argv ]
454 for { set i 0 } { $i < $argc } { incr i } {
455 set option [lindex $argv $i]
457 # make all options have two hyphens
458 switch -glob -- $option {
459 "--*" {
461 "-*" {
462 set option "-$option"
466 # split out the argument for options that take them
467 switch -glob -- $option {
468 "--*=*" {
469 regexp {^[^=]*=(.*)$} $option nil optarg
471 "--bu*" -
472 "--g*" -
473 "--ho*" -
474 "--ig*" -
475 "--loc*" -
476 "--m*" -
477 "--ob*" -
478 "--ou*" -
479 "--sr*" -
480 "--str*" -
481 "--ta*" -
482 "--di*" -
483 "--to*" {
484 incr i
485 set optarg [lindex $argv $i]
489 switch -glob -- $option {
490 "--V*" -
491 "--vers*" { # (--version) version numbers
492 send_user "DejaGnu version\t$frame_version\n"
493 send_user "Expect version\t[exp_version]\n"
494 send_user "Tcl version\t[ info tclversion ]\n"
495 exit 0
498 "--bu*" { # (--build) the build host configuration
499 set arg_build_triplet $optarg
500 ::dejagnu::command_line::save_cmd_var arg_build_triplet
501 continue
504 "--g*" { # (--global_init) the global init file name
505 set global_init_file $optarg
506 ::dejagnu::command_line::save_cmd_var global_init_file
507 continue
510 "--host_bo*" {
511 set host_board $optarg
512 ::dejagnu::command_line::save_cmd_var host_board
513 continue
516 "--ho*" { # (--host) the host configuration
517 set arg_host_triplet $optarg
518 ::dejagnu::command_line::save_cmd_var arg_host_triplet
519 continue
522 "--loc*" { # (--local_init) the local init file name
523 set local_init_file $optarg
524 ::dejagnu::command_line::save_cmd_var local_init_file
525 continue
528 "--ob*" { # (--objdir) where the test case object code lives
529 set objdir $optarg
530 ::dejagnu::command_line::save_cmd_var objdir
531 continue
534 "--sr*" { # (--srcdir) where the testsuite source code lives
535 set srcdir $optarg
536 ::dejagnu::command_line::save_cmd_var srcdir
537 continue
540 "--target_bo*" {
541 set target_list $optarg
542 ::dejagnu::command_line::save_cmd_var target_list
543 continue
546 "--ta*" { # (--target) the target configuration
547 set arg_target_triplet $optarg
548 ::dejagnu::command_line::save_cmd_var arg_target_triplet
549 continue
552 "--tool_opt*" {
553 set TOOL_OPTIONS $optarg
554 ::dejagnu::command_line::save_cmd_var TOOL_OPTIONS
555 continue
558 "--tool_exec*" {
559 set TOOL_EXECUTABLE $optarg
560 ::dejagnu::command_line::save_cmd_var TOOL_EXECUTABLE
561 continue
564 "--to*" { # (--tool) specify tool name
565 set tool $optarg
566 set comm_line_tool $optarg
567 ::dejagnu::command_line::save_cmd_var tool
568 ::dejagnu::command_line::save_cmd_var comm_line_tool
569 continue
572 "--di*" {
573 set cmdline_dir_to_run $optarg
574 ::dejagnu::command_line::save_cmd_var cmdline_dir_to_run
575 continue
578 "--v" -
579 "--verb*" { # (--verbose) verbose output
580 incr verbose
581 continue
584 "[A-Z0-9_-.]*=*" { # process makefile style args like CC=gcc, etc...
585 if {[regexp "^(\[A-Z0-9_-\]+)=(.*)$" $option junk var val]} {
586 set $var $val
587 verbose "$var is now $val"
588 append makevars "set $var $val;" ;# FIXME: Used anywhere?
589 unset junk var val
590 } else {
591 send_error "Illegal variable specification:\n"
592 send_error "$option\n"
594 continue
599 verbose "Verbose level is $verbose"
601 verbose [concat "Initial working directory is" [pwd]]
603 ::dejagnu::command_line::dump_cmd_vars
606 # get the users login name
608 if { $logname eq "" } {
609 if {[info exists env(USER)]} {
610 set logname $env(USER)
611 } else {
612 if {[info exists env(LOGNAME)]} {
613 set logname $env(LOGNAME)
614 } else {
615 # try getting it with whoami
616 catch "set logname [exec whoami]" tmp
617 if {[string match "*couldn't find*to execute*" $tmp]} {
618 # try getting it with who am i
619 unset tmp
620 catch "set logname [exec who am i]" tmp
621 if {[string match "*Command not found*" $tmp]} {
622 send_user "ERROR: couldn't get the users login name\n"
623 set logname "Unknown"
624 } else {
625 set logname [lindex [split $logname " !"] 1]
632 verbose "Login name is $logname"
635 # lookfor_file -- try to find a file by searching up multiple directory levels
637 proc lookfor_file { dir name } {
638 foreach x [list . .. ../.. ../../.. ../../../..] {
639 verbose $dir/$x/$name 2
640 if {[file exists [file join $dir $name]]} {
641 return [file join $dir $name]
643 set dir [remote_file build dirname $dir]
645 return ""
649 # load_lib -- load a library by sourcing it
651 # If there a multiple files with the same name, stop after the first one found.
652 # The order is first look in the install dir, then in a parallel dir in the
653 # source tree (up one or two levels), then in the current dir.
655 proc load_lib { file } {
656 global verbose execpath tool
657 global libdir libdirs srcdir testsuitedir base_dir
658 global loaded_libs
660 if {[info exists loaded_libs($file)]} {
661 return
664 set loaded_libs($file) ""
665 set search_dirs [list ../lib $libdir $libdir/lib]
666 lappend search_dirs [file dirname [file dirname $srcdir]]/dejagnu/lib
667 lappend search_dirs $testsuitedir/lib
668 lappend search_dirs $execpath/lib "."
669 lappend search_dirs [file dirname [file dirname [file dirname $srcdir]]]/dejagnu/lib
670 if {[info exists libdirs]} {
671 lappend search_dirs $libdirs
673 if { [search_and_load_file "library file" $file $search_dirs ] == 0 } {
674 send_error "ERROR: Couldn't find library file $file.\n"
675 exit 1
680 # Begin sourcing the config files.
681 # All are sourced in order.
683 # Search order:
684 # (local) $base_dir/$local_init_file -> $objdir/$local_init_file ->
685 # (global) installed($global_init_file) -> $DEJAGNU -> $HOME/.dejagnurc
687 # For the normal case, we expect $base_dir/$local_init_file to set
688 # host_triplet and target_triplet.
691 load_file [file join $base_dir $local_init_file]
693 # Ensure that command line parameters override testsuite init files.
694 ::dejagnu::command_line::restore_cmd_vars
697 # If objdir didn't get set in $base_dir/$local_init_file, set it to
698 # $base_dir. Make sure we source $objdir/$local_init_file in case
699 # $base_dir/$local_init_file doesn't exist and objdir was given on the
700 # command line.
703 if { $objdir eq "." || $objdir eq $srcdir } {
704 set objdir $base_dir
705 } else {
706 load_file [file join $objdir $local_init_file]
709 # Ensure that command line parameters override testsuite init files.
710 ::dejagnu::command_line::restore_cmd_vars
713 # Find the testsuite.
716 # The DejaGnu manual has always stated that a testsuite must be in a
717 # testsuite/ subdirectory.
719 verbose "Finding testsuite ..." 3
720 verbose "\$base_dir -> $base_dir" 3
721 verbose "\$srcdir -> $srcdir" 3
722 verbose "\$objdir -> $objdir" 3
723 verbose [concat "file tail \$srcdir -> " [file tail $srcdir]] 3
724 verbose [concat "file join \$srcdir testsuite -> " \
725 [file join $srcdir testsuite]] 3
726 verbose [concat "file isdirectory [file join \$srcdir testsuite] -> " \
727 [file isdirectory [file join $srcdir testsuite]]] 3
728 verbose [concat "file tail \$base_dir -> " [file tail $base_dir]] 3
730 if { [file tail $srcdir] eq "testsuite" } {
731 # Subdirectory case -- $srcdir includes testsuite/
732 set testsuitedir $srcdir
733 set testbuilddir $objdir
734 } elseif { [file tail $srcdir] ne "testsuite"
735 && [file isdirectory [file join $srcdir testsuite]] } {
736 # Top-level case -- testsuite in $srcdir/testsuite/
737 set testsuitedir [file join $srcdir testsuite]
738 set testbuilddir [file join $objdir testsuite]
739 } elseif { $srcdir eq "." && [file tail $base_dir] eq "testsuite" } {
740 # Development scaffold case -- testsuite in ".", but "." is "testsuite"
741 set testsuitedir $base_dir
742 set testbuilddir $base_dir
743 } else {
744 if { $testsuitedir eq "testsuite" && $srcdir eq "." && $objdir eq "." } {
745 # Broken legacy case -- testsuite not actually in testsuite/
746 # Produce a warning, but continue.
747 send_error "WARNING: testsuite is not in a testsuite/ directory.\n"
748 set testsuitedir $srcdir
749 set testbuilddir $objdir
750 } else {
751 # Custom case -- all variables are assumed to have been set correctly
755 verbose "Finding testsuite ... done" 3
757 # Well, this just demonstrates the real problem...
758 if {![info exists tool_root_dir]} {
759 set tool_root_dir [file dirname $objdir]
760 if {[file exists [file join $tool_root_dir testsuite]]} {
761 set tool_root_dir [file dirname $tool_root_dir]
765 verbose "Using test sources in $srcdir"
766 verbose "Using test binaries in $objdir"
767 verbose "Testsuite root is $testsuitedir"
768 verbose "Tool root directory is $tool_root_dir"
770 set execpath [file dirname $argv0]
772 # The runtest.exp file is installed directly in libdir.
773 # Conveniently, the source tree layout is the same as the installed libdir.
774 set libdir [file dirname $argv0]
775 if {[info exists env(DEJAGNULIBS)]} {
776 set libdir $env(DEJAGNULIBS)
778 # list of extra search directories used by load_lib to look for libs
779 set libdirs {}
781 verbose "Using $libdir to find libraries"
784 # If the host or target was given on the command line, override the above
785 # config files. We allow $DEJAGNU to massage them though in case it would
786 # ever want to do such a thing.
788 if { $arg_host_triplet ne "" } {
789 set host_triplet $arg_host_triplet
791 if { $arg_build_triplet ne "" } {
792 set build_triplet $arg_build_triplet
795 # If we only specify --host, then that must be the build machine too,
796 # and we're stuck using the old functionality of a simple cross test.
797 if {[expr { $build_triplet eq "" && $host_triplet ne "" } ]} {
798 set build_triplet $host_triplet
800 # If we only specify --build, then we'll use that as the host too.
801 if {[expr { $build_triplet ne "" && $host_triplet eq "" } ]} {
802 set host_triplet $build_triplet
804 unset arg_host_triplet arg_build_triplet
807 # If the build machine type hasn't been specified by now, use config.guess.
810 if {[expr {$build_triplet eq "" && $host_triplet eq ""}]} {
811 # find config.guess
812 foreach dir [list $libdir $libdir/libexec $libdir/.. $execpath $srcdir $srcdir/.. $srcdir/../..] {
813 verbose "Looking for $dir/config.guess" 2
814 if {[file exists [file join $dir config.guess]]} {
815 set config_guess [file join $dir config.guess]
816 verbose "Found [file join $dir config.guess]"
817 break
821 # get the canonical triplet
822 if {![info exists config_guess]} {
823 send_error "ERROR: Couldn't find config.guess program.\n"
824 exit 1
826 catch "exec $config_guess" build_triplet
827 switch -- $build_triplet {
828 "No uname command or uname output not recognized" -
829 "Unable to guess system type" {
830 verbose "WARNING: Uname output not recognized"
831 set build_triplet unknown
834 verbose "Assuming build host is $build_triplet"
835 if { $host_triplet eq "" } {
836 set host_triplet $build_triplet
841 # Figure out the target. If the target hasn't been specified, then we have to
842 # assume we are native.
844 if { $arg_target_triplet ne "" } {
845 set target_triplet $arg_target_triplet
846 } elseif { $target_triplet eq "" } {
847 set target_triplet $build_triplet
848 verbose "Assuming native target is $target_triplet" 2
850 unset arg_target_triplet
852 # Default target_alias to target_triplet.
854 if {![info exists target_alias]} {
855 set target_alias $target_triplet
858 proc get_local_hostname { } {
859 if {[catch "info hostname" hb]} {
860 set hb ""
861 } else {
862 regsub "\\..*$" $hb "" hb
864 verbose "hostname=$hb" 3
865 return $hb
869 # We put these here so that they can be overridden later by site.exp or
870 # friends.
872 # Set up the target as machine NAME. We also load base-config.exp as a
873 # default configuration. The config files are sourced with the global
874 # variable $board set to the name of the current target being defined.
876 proc setup_target_hook { whole_name name } {
877 global board
878 global host_board
880 if {[info exists host_board]} {
881 set hb $host_board
882 } else {
883 set hb [get_local_hostname]
886 set board $whole_name
888 global board_type
889 set board_type "target"
891 load_config base-config.exp
892 if {![load_board_description $name $whole_name $hb]} {
893 if { $name ne "unix" } {
894 perror "couldn't load description file for $name"
895 exit 1
896 } else {
897 load_generic_config "unix"
901 if {[board_info $board exists generic_name]} {
902 load_tool_target_config [board_info $board generic_name]
905 unset board
906 unset board_type
908 push_target $whole_name
910 if { [info procs ${whole_name}_init] ne "" } {
911 ${whole_name}_init $whole_name
914 if { ![isnative] && ![isremote target] } {
915 global env build_triplet target_triplet
916 if { (![info exists env(DEJAGNU)]) && ($build_triplet ne $target_triplet) } {
917 warning "Assuming target board is the local machine (which is probably wrong).\nYou may need to set your DEJAGNU environment variable."
923 # Clean things up afterwards.
925 proc cleanup_target_hook { name } {
926 global tool
927 # Clean up the target board.
928 if { [info procs ${name}_exit] ne "" } {
929 ${name}_exit
931 # We also call the tool exit routine here.
932 if {[info exists tool]} {
933 if { [info procs ${tool}_exit] ne "" } {
934 ${tool}_exit
937 remote_close target
938 pop_target
941 proc setup_host_hook { name } {
942 global board
943 global board_info
944 global board_type
946 set board $name
947 set board_type "host"
949 load_board_description $name
950 unset board
951 unset board_type
952 push_host $name
953 if { [info procs ${name}_init] ne "" } {
954 ${name}_init $name
958 proc setup_build_hook { name } {
959 global board
960 global board_info
961 global board_type
963 set board $name
964 set board_type "build"
966 load_board_description $name
967 unset board
968 unset board_type
969 push_build $name
970 if { [info procs ${name}_init] ne "" } {
971 ${name}_init $name
976 # Find and load the global config file if it exists.
977 # The global config file is used to set the connect mode and other
978 # parameters specific to each particular target.
979 # These files assume the host and target have been set.
982 if { [load_file -- [file join $libdir $global_init_file]] == 0 } {
983 # If $DEJAGNU isn't set either then there isn't any global config file.
984 # Warn the user as there really should be one.
985 if { ! [info exists env(DEJAGNU)] } {
986 send_error "WARNING: Couldn't find the global config file.\n"
990 if {[info exists env(DEJAGNU)]} {
991 if { [load_file -- $env(DEJAGNU)] == 0 } {
992 # It may seem odd to only issue a warning if there isn't a global
993 # config file, but issue an error if $DEJAGNU is erroneously defined.
994 # Since $DEJAGNU is set there is *supposed* to be a global config file,
995 # so the current behaviour seems reasonable.
996 send_error "ERROR: global config file $env(DEJAGNU) not found.\n"
997 exit 1
999 if {![info exists boards_dir]} {
1000 set boards_dir "[file dirname $env(DEJAGNU)]/boards"
1004 # Load user .dejagnurc file last as the ultimate override.
1005 load_file ~/.dejagnurc
1007 if {![info exists boards_dir]} {
1008 set boards_dir ""
1012 # parse out the config parts of the triplet name
1015 # build values
1016 if { $build_cpu eq "" } {
1017 regsub -- "-.*-.*" $build_triplet "" build_cpu
1019 if { $build_vendor eq "" } {
1020 regsub -- "^\[a-z0-9\]*-" $build_triplet "" build_vendor
1021 regsub -- "-.*" $build_vendor "" build_vendor
1023 if { $build_os eq "" } {
1024 regsub -- ".*-.*-" $build_triplet "" build_os
1027 # host values
1028 if { $host_cpu eq "" } {
1029 regsub -- "-.*-.*" $host_triplet "" host_cpu
1031 if { $host_vendor eq "" } {
1032 regsub -- "^\[a-z0-9\]*-" $host_triplet "" host_vendor
1033 regsub -- "-.*" $host_vendor "" host_vendor
1035 if { $host_os eq "" } {
1036 regsub -- ".*-.*-" $host_triplet "" host_os
1039 # target values
1040 if { $target_cpu eq "" } {
1041 regsub -- "-.*-.*" $target_triplet "" target_cpu
1043 if { $target_vendor eq "" } {
1044 regsub -- "^\[a-z0-9\]*-" $target_triplet "" target_vendor
1045 regsub -- "-.*" $target_vendor "" target_vendor
1047 if { $target_os eq "" } {
1048 regsub -- ".*-.*-" $target_triplet "" target_os
1052 # Load the primary tool initialization file.
1055 proc load_tool_init { file } {
1056 global srcdir testsuitedir
1057 global loaded_libs
1059 if {[info exists loaded_libs(tool/$file)]} {
1060 return
1063 set loaded_libs(tool/$file) ""
1065 lappend searchpath [file join $testsuitedir lib tool]
1066 lappend searchpath [file join $testsuitedir lib]
1067 # for legacy testsuites that might have files in lib/ instead of
1068 # testsuite/lib/ in the package source tree; deprecated
1069 lappend searchpath [file join $srcdir lib]
1071 if { ![search_and_load_file "tool init file" [list $file] $searchpath] } {
1072 warning "Couldn't find tool init file"
1077 # load the testing framework libraries
1079 load_lib utils.exp
1080 load_lib framework.exp
1081 load_lib debugger.exp
1082 load_lib remote.exp
1083 load_lib target.exp
1084 load_lib targetdb.exp
1085 load_lib libgloss.exp
1087 # Initialize the test counters and reset them to 0.
1088 init_testcounts
1089 reset_vars
1092 # Parse the command line arguments.
1095 # Load the tool initialization file. Allow the --tool option to override
1096 # what's set in the site.exp file.
1097 if {[info exists comm_line_tool]} {
1098 set tool $comm_line_tool
1101 if {[info exists tool]} {
1102 load_tool_init ${tool}.exp
1105 set argc [ llength $argv ]
1106 for { set i 0 } { $i < $argc } { incr i } {
1107 set option [ lindex $argv $i ]
1109 # make all options have two hyphens
1110 switch -glob -- $option {
1111 "--*" {
1113 "-*" {
1114 set option "-$option"
1118 # split out the argument for options that take them
1119 switch -glob -- $option {
1120 "--*=*" {
1121 regexp {^[^=]*=(.*)$} $option nil optarg
1123 "--bu*" -
1124 "--g*" -
1125 "--ho*" -
1126 "--ig*" -
1127 "--loc*" -
1128 "--m*" -
1129 "--ob*" -
1130 "--ou*" -
1131 "--sr*" -
1132 "--str*" -
1133 "--ta*" -
1134 "--di*" -
1135 "--to*" {
1136 incr i
1137 set optarg [lindex $argv $i]
1141 switch -glob -- $option {
1142 "--v*" { # (--verbose) verbose output
1143 # Already parsed.
1144 continue
1147 "--g*" { # (--global_init) the global init file name
1148 # Already parsed (and no longer useful). The file has been loaded.
1149 continue
1152 "--loc*" { # (--local_init) the local init file name
1153 # Already parsed (and no longer useful). The file has been loaded.
1154 continue
1157 "--bu*" { # (--build) the build host configuration
1158 # Already parsed (and don't set again). Let $DEJAGNU rename it.
1159 continue
1162 "--ho*" { # (--host) the host configuration
1163 # Already parsed (and don't set again). Let $DEJAGNU rename it.
1164 continue
1167 "--target_bo*" {
1168 # Set it again, father knows best.
1169 set target_list $optarg
1170 continue
1173 "--ta*" { # (--target) the target configuration
1174 # Already parsed (and don't set again). Let $DEJAGNU rename it.
1175 continue
1178 "--a*" { # (--all) print all test output to screen
1179 set all_flag 1
1180 verbose "Print all test output to screen"
1181 continue
1184 "--di*" {
1185 # Already parsed (and don't set again). Let $DEJAGNU rename it.
1186 continue
1190 "--de*" { # (--debug) expect internal debugging
1191 if {[file exists ./dbg.log]} {
1192 catch [file delete -force -- dbg.log]
1194 if { $verbose > 2 } {
1195 exp_internal -f dbg.log 1
1196 } else {
1197 exp_internal -f dbg.log 0
1199 verbose "Expect Debugging is ON"
1200 continue
1203 "--D[01]" { # (-Debug) turn on Tcl debugger
1204 # The runtest shell script handles this option, but it
1205 # still appears in the options in the Tcl code.
1206 verbose "Tcl debugger is ON"
1207 continue
1210 "--m*" { # (--mail) mail the output
1211 set mailing_list $optarg
1212 set mail_logs 1
1213 verbose "Mail results to $mailing_list"
1214 continue
1217 "--r*" { # (--reboot) reboot the target
1218 set reboot 1
1219 verbose "Will reboot the target (if supported)"
1220 continue
1223 "--ob*" { # (--objdir) where the test case object code lives
1224 # Already parsed, but parse again to make sure command line
1225 # options override any config file.
1226 set objdir $optarg
1227 verbose "Using test binaries in $objdir"
1228 continue
1231 "--ou*" { # (--outdir) where to put the output files
1232 set outdir $optarg
1233 verbose "Test output put in $outdir"
1234 continue
1237 "--log_dialog*" {
1238 incr log_dialog
1239 continue
1242 "*.exp" { # specify test names to run
1243 set all_runtests($option) ""
1244 verbose "Running only tests $option"
1245 continue
1248 "*.exp=*" { # specify test names to run
1249 set tmp [split $option "="]
1250 set all_runtests([lindex $tmp 0]) [lindex $tmp 1]
1251 verbose "Running only tests $option"
1252 unset tmp
1253 continue
1256 "--ig*" { # (--ignore) specify test names to exclude
1257 set ignoretests $optarg
1258 verbose "Ignoring test $ignoretests"
1259 continue
1262 "--sr*" { # (--srcdir) where the testsuite source code lives
1263 # Already parsed, but parse again to make sure command line
1264 # options override any config file.
1266 set srcdir $optarg
1267 continue
1270 "--str*" { # (--strace) expect trace level
1271 set tracelevel $optarg
1272 strace $tracelevel
1273 verbose "Source Trace level is now $tracelevel"
1274 continue
1277 "--sta*" { # (--status) exit status flag
1278 # preserved for compatability, do nothing
1279 continue
1282 "--tool_opt*" {
1283 continue
1286 "--tool_exec*" {
1287 set TOOL_EXECUTABLE $optarg
1288 continue
1291 "--to*" { # (--tool) specify tool name
1292 set tool $optarg
1293 verbose "Testing $tool"
1294 continue
1297 "--x*" {
1298 set xml 1
1299 verbose "XML logging turned on"
1300 continue
1303 "--he*" { # (--help) help text
1304 usage
1305 exit 0
1308 "[A-Z0-9_-.]*=*" { # skip makefile style args like CC=gcc, etc... (processed in first pass)
1309 continue
1312 default {
1313 if {[info exists tool]} {
1314 if { [info procs ${tool}_option_proc] ne "" } {
1315 if {[${tool}_option_proc $option]} {
1316 continue
1320 send_error "\nIllegal Argument \"$option\"\n"
1321 send_error "try \"runtest --help\" for option list\n"
1322 exit 1
1328 # check for a few crucial variables
1330 if {![info exists tool]} {
1331 send_error "WARNING: No tool specified\n"
1332 set tool ""
1336 # initialize a few Tcl variables to something other than their default
1338 if { $verbose > 2 || $log_dialog } {
1339 log_user 1
1340 } else {
1341 log_user 0
1344 set timeout 10
1349 # open log files
1351 open_logs
1353 # print the config info
1354 clone_output "Test run by $logname on [timestamp -format %c]"
1355 if {[is3way]} {
1356 clone_output "Target is $target_triplet"
1357 clone_output "Host is $host_triplet"
1358 clone_output "Build is $build_triplet"
1359 } else {
1360 if {[isnative]} {
1361 clone_output "Native configuration is $target_triplet"
1362 } else {
1363 clone_output "Target is $target_triplet"
1364 clone_output "Host is $host_triplet"
1368 clone_output "\n\t\t=== $tool tests ===\n"
1371 # Look for the generic board configuration file. It searches in several
1372 # places: $libdir/config, $libdir/../config, and $boards_dir.
1375 proc load_generic_config { name } {
1376 global libdir
1377 global board
1378 global board_info
1379 global boards_dir
1380 global board_type
1382 if {[info exists board]} {
1383 if {![info exists board_info($board,generic_name)]} {
1384 set board_info($board,generic_name) $name
1388 if {[info exists board_type]} {
1389 set type "for $board_type"
1390 } else {
1391 set type ""
1394 set dirlist [concat $libdir/config [file dirname $libdir]/config $boards_dir]
1395 set result [search_and_load_file "generic interface file $type" $name.exp $dirlist]
1397 return $result
1401 # Load the tool-specific target description.
1403 proc load_config { args } {
1404 global testsuitedir
1406 set found 0
1408 return [search_and_load_file "tool-and-target-specific interface file" $args [list $testsuitedir/config $testsuitedir/../config $testsuitedir/../../config $testsuitedir/../../../config]]
1412 # Find the files that set up the configuration for the target. There
1413 # are assumed to be two of them; one defines a basic set of
1414 # functionality for the target that can be used by all tool
1415 # testsuites, and the other defines any necessary tool-specific
1416 # functionality. These files are loaded via load_config.
1418 # These used to all be named $target_abbrev-$tool.exp, but as the
1419 # $tool variable goes away, it's now just $target_abbrev.exp. First
1420 # we look for a file named with both the abbrev and the tool names.
1421 # Then we look for one named with just the abbrev name. Finally, we
1422 # look for a file called default, which is the default actions, as
1423 # some tools could be purely host based. Unknown is mostly for error
1424 # trapping.
1427 proc load_tool_target_config { name } {
1428 global target_os libdir testsuitedir
1430 set found [load_config $name.exp $target_os.exp "default.exp" "unknown.exp"]
1432 if { $found == 0 } {
1433 send_error "WARNING: Couldn't find tool config file for $name, using default.\n"
1434 # If we can't load the tool init file, this must be a simple natively hosted
1435 # test suite, so we use the default procs for Unix.
1436 if { [search_and_load_file "library file" default.exp [list $libdir $libdir/config [file dirname [file dirname $testsuitedir]]/dejagnu/config $testsuitedir/config . [file dirname [file dirname [file dirname $testsuitedir]]]/dejagnu/config]] == 0 } {
1437 send_error "ERROR: Couldn't find default tool init file.\n"
1438 exit 1
1444 # Find the file that describes the machine specified by board_name.
1447 proc load_board_description { board_name args } {
1448 global libdir
1449 global board
1450 global board_info
1451 global boards_dir
1452 global board_type
1454 set dejagnu ""
1456 if { [llength $args] > 0 } {
1457 set whole_name [lindex $args 0]
1458 } else {
1459 set whole_name $board_name
1462 set board_info($whole_name,name) $whole_name
1463 if {![info exists board]} {
1464 set board $whole_name
1465 set board_set 1
1466 } else {
1467 set board_set 0
1470 set dirlist {}
1471 if { [llength $args] > 1 } {
1472 set suffix [lindex $args 1]
1473 if { $suffix ne "" } {
1474 foreach x $boards_dir {
1475 lappend dirlist $x/$suffix
1477 lappend dirlist $libdir/baseboards/$suffix
1480 set dirlist [concat $dirlist $boards_dir]
1481 lappend dirlist $libdir/baseboards
1482 verbose "dirlist is $dirlist"
1483 if {[info exists board_type]} {
1484 set type "for $board_type"
1485 } else {
1486 set type ""
1488 if {![info exists board_info($whole_name,isremote)]} {
1489 set board_info($whole_name,isremote) 1
1490 if {[info exists board_type]} {
1491 if { $board_type eq "build" } {
1492 set board_info($whole_name,isremote) 0
1495 if { $board_name eq [get_local_hostname] } {
1496 set board_info($whole_name,isremote) 0
1499 search_and_load_file "standard board description file $type" standard.exp $dirlist
1500 set found [search_and_load_file "board description file $type" $board_name.exp $dirlist]
1501 if { $board_set != 0 } {
1502 unset board
1505 return $found
1509 # Find the base-level file that describes the machine specified by args. We
1510 # only look in one directory, $libdir/baseboards.
1513 proc load_base_board_description { board_name } {
1514 global libdir
1515 global board
1516 global board_info
1517 global board_type
1519 set board_set 0
1520 set board_info($board_name,name) $board_name
1521 if {![info exists board]} {
1522 set board $board_name
1523 set board_set 1
1525 if {[info exists board_type]} {
1526 set type "for $board_type"
1527 } else {
1528 set type ""
1530 if {![info exists board_info($board_name,isremote)]} {
1531 set board_info($board_name,isremote) 1
1532 if {[info exists board_type]} {
1533 if { $board_type eq "build" } {
1534 set board_info($board_name,isremote) 0
1539 if { $board_name eq [get_local_hostname] } {
1540 set board_info($board_name,isremote) 0
1542 set found [search_and_load_file "board description file $type" $board_name.exp [list $libdir/baseboards]]
1543 if { $board_set != 0 } {
1544 unset board
1547 return $found
1551 # Source the testcase in TEST_FILE_NAME.
1554 proc runtest { test_file_name } {
1555 global prms_id
1556 global bug_id
1557 global test_result
1558 global errcnt
1559 global errorCode
1560 global errorInfo
1561 global tool
1562 global testdir
1564 clone_output "Running $test_file_name ..."
1565 set prms_id 0
1566 set bug_id 0
1567 set test_result ""
1569 # set testdir so testsuite file -test has a starting point
1570 set testdir [file dirname $test_file_name]
1572 if {[file exists $test_file_name]} {
1573 set timestart [timestamp]
1575 if {[info exists tool]} {
1576 if { [info procs ${tool}_init] ne "" } {
1577 ${tool}_init $test_file_name
1581 if { [catch "uplevel #0 source $test_file_name" msg] == 1 } {
1582 # If we have a Tcl error, propagate the exit status so
1583 # that 'make' (if it invokes runtest) notices the error.
1584 global exit_status exit_error
1585 # exit error is set by the --status command line option
1586 if { $exit_status == 0 } {
1587 set exit_status 2
1589 set new_error [list $test_file_name $msg]
1590 # We can't call `perror' here, it resets `errorInfo'
1591 # before we want to look at it. Also remember that perror
1592 # increments `errcnt'. If we do call perror we'd have to
1593 # reset errcnt afterwards.
1594 clone_output "ERROR: tcl error sourcing $test_file_name."
1595 if {[info exists errorCode]} {
1596 clone_output "ERROR: tcl error code $errorCode"
1597 lappend new_error $errorCode
1598 } else {
1599 lappend new_error [list]
1601 if {[info exists errorInfo]} {
1602 clone_output "ERROR: $errorInfo"
1603 lappend new_error $errorInfo
1604 unset errorInfo
1605 } else {
1606 lappend new_error [list]
1608 lappend ::dejagnu::error::list $new_error
1609 unresolved "testcase '$test_file_name' aborted due to Tcl error"
1612 if {[info exists tool]} {
1613 if { [info procs ${tool}_finish] ne "" } {
1614 ${tool}_finish
1617 set timeend [timestamp]
1618 set timediff [expr {$timeend - $timestart}]
1619 verbose -log "testcase $test_file_name completed in $timediff seconds" 4
1620 } else {
1621 # This should never happen, but maybe if the file got removed
1622 # between the `find' above and here.
1623 perror "$test_file_name does not exist." 0
1627 # Trap some signals so we know what's happening. These replace the previous
1628 # ones because we've now loaded the library stuff.
1630 if {![exp_debug]} {
1631 foreach sig {{SIGINT {interrupted by user} 130} \
1632 {SIGQUIT {interrupted by user} 131} \
1633 {SIGTERM {terminated} 143}} {
1634 set signal [lindex $sig 0]
1635 set str [lindex $sig 1]
1636 set code [lindex $sig 2]
1637 trap "send_error \"got a \[trap -name\] signal, $str \\n\"; set exit_status $code; log_and_exit;" $signal
1638 verbose "setting trap for $signal to $str" 1
1640 unset signal str sig
1644 # Given a list of targets, process any iterative lists.
1646 proc process_target_variants { target_list } {
1647 set result {}
1648 foreach x $target_list {
1649 if {[regexp "\\(" $x]} {
1650 regsub {^.*\(([^()]*)\)$} $x {\1} variant_list
1651 regsub {\([^(]*$} $x "" x
1652 set list [process_target_variants $x]
1653 set result {}
1654 foreach x $list {
1655 set result [concat $result [iterate_target_variants $x [split $variant_list ","]]]
1657 } elseif {[regexp "\{" $x]} {
1658 regsub "^.*\{(\[^\{\}\]*)\}$" $x {\1} variant_list
1659 regsub "\{\[^\{\]*$" $x "" x
1660 set list [process_target_variants $x]
1661 foreach x $list {
1662 foreach i [split $variant_list ","] {
1663 set name $x
1664 if { $i ne "" } {
1665 append name "/" $i
1667 lappend result $name
1670 } else {
1671 lappend result $x
1674 return $result
1677 proc iterate_target_variants { target variants } {
1678 return [iterate_target_variants_two $target $target $variants]
1682 # Given a list of variants, produce the list of all possible combinations.
1684 proc iterate_target_variants_two { orig_target target variants } {
1686 if { [llength $variants] == 0 } {
1687 return [list $target]
1688 } else {
1689 if { [llength $variants] > 1 } {
1690 set result [iterate_target_variants_two $orig_target $target [lrange $variants 1 end]]
1691 } else {
1692 if { $target ne $orig_target } {
1693 set result [list $target]
1694 } else {
1695 set result {}
1698 if { [lindex $variants 0] ne "" } {
1699 append target "/" [lindex $variants 0]
1700 return [concat $result [iterate_target_variants_two $orig_target $target [lrange $variants 1 end]]]
1701 } else {
1702 return [concat $result $target]
1707 setup_build_hook [get_local_hostname]
1709 if {[info exists host_board]} {
1710 setup_host_hook $host_board
1711 } else {
1712 set hb [get_local_hostname]
1713 if { $hb ne "" } {
1714 setup_host_hook $hb
1719 # main test execution loop
1722 if {[info exists errorInfo]} {
1723 unset errorInfo
1727 # make sure we have only single path delimiters
1728 regsub -all {([^/])//*} $srcdir {\1/} srcdir
1729 regsub -all {([^/])//*} $objdir {\1/} objdir
1730 regsub -all {([^/])//*} $testsuitedir {\1/} testsuitedir
1731 regsub -all {([^/])//*} $testbuilddir {\1/} testbuilddir
1733 if {![info exists target_list]} {
1734 # Make sure there is at least one target machine. It's probably a Unix box,
1735 # but that's just a guess.
1736 set target_list { "unix" }
1737 } else {
1738 verbose "target list is $target_list"
1742 # Iterate through the list of targets.
1744 global current_target
1746 set target_list [process_target_variants $target_list]
1748 set target_count [llength $target_list]
1750 clone_output "Schedule of variations:"
1751 foreach current_target $target_list {
1752 clone_output " $current_target"
1754 clone_output ""
1757 foreach current_target $target_list {
1758 verbose "target is $current_target"
1759 set current_target_name $current_target
1760 set tlist [split $current_target /]
1761 set current_target [lindex $tlist 0]
1762 set board_variant_list [lrange $tlist 1 end]
1764 # Set the counts for this target to 0.
1765 reset_vars
1766 clone_output "Running target $current_target_name"
1768 setup_target_hook $current_target_name $current_target
1770 # If multiple passes requested, set them up. Otherwise prepare just one.
1771 # The format of `MULTIPASS' is a list of elements containing
1772 # "{ name var1=value1 ... }" where `name' is a generic name for the pass and
1773 # currently has no other meaning.
1775 global env
1777 if { [info exists MULTIPASS] } {
1778 set multipass $MULTIPASS
1780 if { $multipass eq "" } {
1781 set multipass { "" }
1784 # If PASS is specified, we want to run only the tests specified.
1785 # Its value should be a number or a list of numbers that specify
1786 # the passes that we want to run.
1787 if {[info exists PASS]} {
1788 set pass $PASS
1789 } else {
1790 set pass ""
1793 if {$pass ne ""} {
1794 set passes [list]
1795 foreach p $pass {
1796 foreach multipass_elem $multipass {
1797 set multipass_name [lindex $multipass_elem 0]
1798 if {$p == $multipass_name} {
1799 lappend passes $multipass_elem
1800 break
1804 set multipass $passes
1807 foreach pass $multipass {
1809 # multipass_name is set for `record_test' to use (see framework.exp).
1810 if { [lindex $pass 0] ne "" } {
1811 set multipass_name [lindex $pass 0]
1812 clone_output "Running pass `$multipass_name' ..."
1813 } else {
1814 set multipass_name ""
1816 set restore ""
1817 foreach varval [lrange $pass 1 end] {
1818 set tmp [string first "=" $varval]
1819 set var [string range $varval 0 [expr {$tmp - 1}]]
1820 # Save previous value.
1821 if {[info exists $var]} {
1822 lappend restore "$var [list [eval concat \$$var]]"
1823 } else {
1824 lappend restore $var
1826 # Handle "CFLAGS=$CFLAGS foo".
1827 eval set $var \[string range \"$varval\" [expr {$tmp + 1}] end\]
1828 verbose "$var is now [eval concat \$$var]"
1829 unset tmp var
1832 # look for the top level testsuites. if $tool doesn't
1833 # exist and there are no subdirectories in $testsuitedir, then
1834 # we print a warning and default to srcdir.
1835 set test_top_dirs [lsort [getdirs -all $testsuitedir $tool*]]
1836 if { $test_top_dirs eq "" } {
1837 send_error "WARNING: could not find testsuite; trying $srcdir.\n"
1838 set test_top_dirs [list $srcdir]
1839 } else {
1840 # JYG:
1841 # DejaGNU's notion of test tree and test files is very
1842 # general:
1843 # given $testsuitedir and $tool, any subdirectory (at any
1844 # level deep) with the "$tool" prefix starts a test tree
1845 # given a test tree, any *.exp file underneath (at any
1846 # level deep) is a test file.
1848 # For test tree layouts with $tool prefix on
1849 # both a parent and a child directory, we need to eliminate
1850 # the child directory entry from test_top_dirs list.
1851 # e.g. gdb.hp/gdb.base-hp/ would result in two entries
1852 # in the list: gdb.hp, gdb.hp/gdb.base-hp.
1853 # If the latter not eliminated, test files under
1854 # gdb.hp/gdb.base-hp would be run twice (since test files
1855 # are gathered from all sub-directories underneath a
1856 # directory).
1858 # Since $tool may be g++, etc. which could confuse
1859 # regexp, we cannot do the simpler test:
1860 # ...
1861 # if [regexp "$testsuitedir/.*$tool.*/.*$tool.*" $dir]
1862 # ...
1863 # instead, we rely on the fact that test_top_dirs is
1864 # a sorted list of entries, and any entry that contains
1865 # the previous valid test top dir entry in its own pathname
1866 # must be excluded.
1868 set temp_top_dirs [list]
1869 set prev_dir ""
1870 foreach dir $test_top_dirs {
1871 if { $prev_dir eq ""
1872 || [string first $prev_dir/ $dir] == -1 } {
1873 # the first top dir entry, or an entry that
1874 # does not share the previous entry's entire
1875 # pathname, record it as a valid top dir entry.
1877 lappend temp_top_dirs $dir
1878 set prev_dir $dir
1881 set test_top_dirs $temp_top_dirs
1883 verbose "Top level testsuite dirs are $test_top_dirs" 2
1884 set testlist ""
1885 if {[array exists all_runtests]} {
1886 foreach x [array names all_runtests] {
1887 verbose "trying to glob $testsuitedir/$x" 2
1888 set s [glob -nocomplain $testsuitedir/$x]
1889 if { $s ne "" } {
1890 set testlist [concat $testlist $s]
1895 # If we have a list of tests, run all of them.
1897 if { $testlist ne "" } {
1898 foreach test_name $testlist {
1899 if { $ignoretests ne "" } {
1900 if { 0 <= [lsearch $ignoretests [file tail $test_name]]} {
1901 continue
1905 # set subdir to the tail of the dirname after $srcdir,
1906 # for the driver files that want it. XXX this is silly.
1907 # drivers should get a single var, not $srcdir/$subdir
1908 set subdir [relative_filename $srcdir \
1909 [file dirname $test_name]]
1911 # XXX not the right thing to do.
1912 set runtests [list [file tail $test_name] ""]
1914 runtest $test_name
1916 } else {
1918 # Go digging for tests.
1920 foreach dir $test_top_dirs {
1921 if { $dir ne $testsuitedir } {
1922 # Ignore this directory if is a directory to be
1923 # ignored.
1924 if {[info exists ignoredirs] && $ignoredirs ne ""} {
1925 set found 0
1926 foreach directory $ignoredirs {
1927 if {[string match *$directory* $dir]} {
1928 set found 1
1929 break
1932 if { $found } {
1933 continue
1937 # Run the test if dir_to_run was specified as a
1938 # value (for example in MULTIPASS) and the test
1939 # directory matches that directory.
1940 if {[info exists dir_to_run] && $dir_to_run ne ""} {
1941 # JYG: dir_to_run might be a space delimited list
1942 # of directories. Look for match on each item.
1943 set found 0
1944 foreach directory $dir_to_run {
1945 if {[string match *$directory* $dir]} {
1946 set found 1
1947 break
1950 if {!$found} {
1951 continue
1955 # Run the test if cmdline_dir_to_run was specified
1956 # by the user using --directory and the test
1957 # directory matches that directory
1958 if {[info exists cmdline_dir_to_run] \
1959 && $cmdline_dir_to_run ne ""} {
1960 # JYG: cmdline_dir_to_run might be a space delimited
1961 # list of directories. Look for match on each item.
1962 set found 0
1963 foreach directory $cmdline_dir_to_run {
1964 # Look for a directory that ends with the
1965 # provided --directory name.
1966 if {[string match $directory $dir]
1967 || [string match "*/$directory" $dir]} {
1968 set found 1
1969 break
1972 if {!$found} {
1973 continue
1977 foreach test_name [lsort [find $dir *.exp]] {
1978 if { $test_name eq "" } {
1979 continue
1981 # Ignore this one if asked to.
1982 if { $ignoretests ne "" } {
1983 if { 0 <= [lsearch $ignoretests [file tail $test_name]]} {
1984 continue
1988 # Get the path after the $srcdir so we know
1989 # the subdir we're in.
1990 set subdir [relative_filename $srcdir \
1991 [file dirname $test_name]]
1992 # Check to see if the range of tests is limited,
1993 # set `runtests' to a list of two elements: the script name
1994 # and any arguments ("" if none).
1995 if {[array exists all_runtests]} {
1996 verbose "searching for $test_name in [array names all_runtests]" 2
1997 if { 0 > [lsearch [array names all_runtests] [file tail $test_name]]} {
1998 if { 0 > [lsearch [array names all_runtests] $test_name] } {
1999 continue
2002 set runtests [list [file tail $test_name] $all_runtests([file tail $test_name])]
2003 } else {
2004 set runtests [list [file tail $test_name] ""]
2006 runtest $test_name
2012 # Restore the variables set by this pass.
2013 foreach varval $restore {
2014 if { [llength $varval] > 1 } {
2015 verbose "Restoring [lindex $varval 0] to [lindex $varval 1]" 4
2016 set [lindex $varval 0] [lindex $varval 1]
2017 } else {
2018 verbose "Restoring [lindex $varval 0] to `unset'" 4
2019 unset -- [lindex $varval 0]
2023 cleanup_target_hook $current_target
2024 if { $target_count > 1 } {
2025 log_summary
2029 log_and_exit