aboutsummaryrefslogtreecommitdiff
path: root/test/testrunner.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'test/testrunner.tcl')
-rw-r--r--test/testrunner.tcl549
1 files changed, 441 insertions, 108 deletions
diff --git a/test/testrunner.tcl b/test/testrunner.tcl
index 0c704daf2..d3a2c1f4c 100644
--- a/test/testrunner.tcl
+++ b/test/testrunner.tcl
@@ -54,22 +54,37 @@ proc usage {} {
Usage:
$a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?
$a0 PERMUTATION FILE
+ $a0 errors ?-v|--verbose?
+ $a0 help
$a0 njob ?NJOB?
- $a0 status
+ $a0 script ?-msvc? CONFIG
+ $a0 status ?-d SECS? ?--cls?
where SWITCHES are:
- --buildonly
- --dryrun
- --jobs NUMBER-OF-JOBS
- --zipvfs ZIPVFS-SOURCE-DIR
+ --buildonly Build test exes but do not run tests
+ --config CONFIGS Only use configs on comma-separate list CONFIGS
+ --dryrun Write what would have happened to testrunner.log
+ --explain Write summary to stdout
+ --jobs NUM Run tests using NUM separate processes
+ --omit CONFIGS Omit configs on comma-separated list CONFIGS
+ --status Show the full "status" report while running
+ --stop-on-coredump Stop running if any test segfaults
+ --stop-on-error Stop running after any reported error
+ --zipvfs ZIPVFSDIR ZIPVFS source directory
+
+Special values for PERMUTATION that work with plain tclsh:
+
+ list - show all allowed PERMUTATION arguments.
+ mdevtest - tests recommended prior to normal development check-ins.
+ release - full release test with various builds.
+ sdevtest - like mdevtest but using ASAN and UBSAN.
-Interesting values for PERMUTATION are:
+Other PERMUTATION arguments must be run using testfixture, not tclsh:
- veryquick - a fast subset of the tcl test scripts. This is the default.
- full - all tcl test scripts.
all - all tcl test scripts, plus a subset of test scripts rerun
with various permutations.
- release - full release test with various builds.
+ full - all tcl test scripts.
+ veryquick - a fast subset of the tcl test scripts. This is the default.
If no PATTERN arguments are present, all tests specified by the PERMUTATION
are run. Otherwise, each pattern is interpreted as a glob pattern. Only
@@ -87,8 +102,20 @@ with the specified permutation.
The "status" and "njob" commands are designed to be run from the same
directory as a running testrunner.tcl script that is running tests. The
"status" command prints a report describing the current state and progress
-of the tests. The "njob" command may be used to query or modify the number
-of sub-processes the test script uses to run tests.
+of the tests. Use the "-d N" option to have the status display clear the
+screen and repeat every N seconds. The "njob" command may be used to query
+or modify the number of sub-processes the test script uses to run tests.
+
+The "script" command outputs the script used to build a configuration.
+Add the "-msvc" option for a Windows-compatible script. For a list of
+available configurations enter "$a0 script help".
+
+The "errors" commands shows the output of all tests that failed in the
+most recent run. Complete output is shown if the -v or --verbose options
+are used. Otherwise, an attempt is made to minimize the output to show
+only the parts that contain the error messages.
+
+Full documentation here: https://sqlite.org/src/doc/trunk/doc/testrunner.md
}]]
exit 1
@@ -126,6 +153,10 @@ proc guess_number_of_cores {} {
}
proc default_njob {} {
+ global env
+ if {[info exists env(NJOB)] && $env(NJOB)>=1} {
+ return $env(NJOB)
+ }
set nCore [guess_number_of_cores]
if {$nCore<=2} {
set nHelper 1
@@ -151,7 +182,13 @@ set TRG(reporttime) 2000
set TRG(fuzztest) 0 ;# is the fuzztest option present.
set TRG(zipvfs) "" ;# -zipvfs option, if any
set TRG(buildonly) 0 ;# True if --buildonly option
+set TRG(config) {} ;# Only build the named configurations
+set TRG(omitconfig) {} ;# Do not build these configurations
set TRG(dryrun) 0 ;# True if --dryrun option
+set TRG(explain) 0 ;# True for the --explain option
+set TRG(stopOnError) 0 ;# Stop running at first failure
+set TRG(stopOnCore) 0 ;# Stop on a core-dump
+set TRG(fullstatus) 0 ;# Full "status" report while running
switch -nocase -glob -- $tcl_platform(os) {
*darwin* {
@@ -159,6 +196,7 @@ switch -nocase -glob -- $tcl_platform(os) {
set TRG(make) make.sh
set TRG(makecmd) "bash make.sh"
set TRG(testfixture) testfixture
+ set TRG(shell) sqlite3
set TRG(run) run.sh
set TRG(runcmd) "bash run.sh"
}
@@ -167,14 +205,16 @@ switch -nocase -glob -- $tcl_platform(os) {
set TRG(make) make.sh
set TRG(makecmd) "bash make.sh"
set TRG(testfixture) testfixture
+ set TRG(shell) sqlite3
set TRG(run) run.sh
set TRG(runcmd) "bash run.sh"
}
*win* {
set TRG(platform) win
set TRG(make) make.bat
- set TRG(makecmd) make.bat
+ set TRG(makecmd) "call make.bat"
set TRG(testfixture) testfixture.exe
+ set TRG(shell) sqlite3.exe
set TRG(run) run.bat
set TRG(runcmd) "run.bat"
}
@@ -239,7 +279,7 @@ set TRG(schema) {
/* Fields updated as jobs run */
starttime INTEGER,
endtime INTEGER,
- state TEXT CHECK( state IN ('', 'ready', 'running', 'done', 'failed') ),
+ state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
output TEXT
);
@@ -327,6 +367,14 @@ if {([llength $argv]==2 || [llength $argv]==1)
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
+# Check if this is the "help" command:
+#
+if {[string compare -nocase help [lindex $argv 0]]==0} {
+ usage
+}
+#--------------------------------------------------------------------------
+
+#--------------------------------------------------------------------------
# Check if this is the "script" command:
#
if {[string compare -nocase script [lindex $argv 0]]==0} {
@@ -340,34 +388,36 @@ if {[string compare -nocase script [lindex $argv 0]]==0} {
puts [trd_buildscript $config [file dirname $testdir] $bMsvc]
exit
}
-
-#--------------------------------------------------------------------------
-# Check if this is the "status" command:
+# Helper routine for show_status
#
-if {[llength $argv]==1
- && [string compare -nocase status [lindex $argv 0]]==0
-} {
-
- proc display_job {jobdict {tm ""}} {
- array set job $jobdict
-
- set dfname [format %-60s $job(displayname)]
-
- set dtm ""
- if {$tm!=""} { set dtm "\[[expr {$tm-$job(starttime)}]ms\]" }
- puts " $dfname $dtm"
+proc display_job {jobdict {tm ""}} {
+ array set job $jobdict
+ set dfname [format %-60s $job(displayname)]
+ set dtm ""
+ if {$tm!=""} {
+ set dtm [format %-10s "\[[expr {$tm-$job(starttime)}]ms\]"]
}
+ puts " $dfname $dtm"
+}
- sqlite3 mydb $TRG(dbname)
- mydb timeout 1000
- mydb eval BEGIN
-
- set cmdline [mydb one { SELECT value FROM config WHERE name='cmdline' }]
- set nJob [mydb one { SELECT value FROM config WHERE name='njob' }]
-
+# This procedure shows the "status" page. It uses the database
+# connect passed in as the "db" parameter. If the "cls" parameter
+# is true, then VT100 escape codes are used to format the display.
+#
+proc show_status {db cls} {
+ global TRG
+ $db eval BEGIN
+ if {[catch {
+ set cmdline [$db one { SELECT value FROM config WHERE name='cmdline' }]
+ set nJob [$db one { SELECT value FROM config WHERE name='njob' }]
+ } msg]} {
+ if {$cls} {puts "\033\[H\033\[2J"}
+ puts "Cannot read database: $TRG(dbname)"
+ return
+ }
set now [clock_milliseconds]
- set tm [mydb one {
+ set tm [$db one {
SELECT
COALESCE((SELECT value FROM config WHERE name='end'), $now) -
(SELECT value FROM config WHERE name='start')
@@ -375,7 +425,7 @@ if {[llength $argv]==1
set total 0
foreach s {"" ready running done failed} { set S($s) 0 }
- mydb eval {
+ $db eval {
SELECT state, count(*) AS cnt FROM jobs GROUP BY 1
} {
incr S($state) $cnt
@@ -384,18 +434,28 @@ if {[llength $argv]==1
set fin [expr $S(done)+$S(failed)]
if {$cmdline!=""} {set cmdline " $cmdline"}
+ if {$cls} {
+ # Move the cursor to the top-left corner. Each iteration will simply
+ # overwrite.
+ puts -nonewline "\033\[H"
+ flush stdout
+ set clreol "\033\[K"
+ } else {
+ set clreol ""
+ }
set f ""
if {$S(failed)>0} {
set f "$S(failed) FAILED, "
}
- puts "Command line: \[testrunner.tcl$cmdline\]"
- puts "Jobs: $nJob"
- puts "Summary: ${tm}ms, ($fin/$total) finished, ${f}$S(running) running"
+ puts "Command line: \[testrunner.tcl$cmdline\]$clreol"
+ puts "Jobs: $nJob "
+ puts "Summary: ${tm}ms, ($fin/$total) finished,\
+ ${f}$S(running) running "
set srcdir [file dirname [file dirname $TRG(info_script)]]
if {$S(running)>0} {
puts "Running: "
- mydb eval {
+ $db eval {
SELECT * FROM jobs WHERE state='running' ORDER BY starttime
} job {
display_job [array get job] $now
@@ -403,17 +463,137 @@ if {[llength $argv]==1
}
if {$S(failed)>0} {
puts "Failures: "
- mydb eval {
+ $db eval {
SELECT * FROM jobs WHERE state='failed' ORDER BY starttime
} job {
display_job [array get job]
}
+ set nOmit [$db one {SELECT count(*) FROM jobs WHERE state='omit'}]
+ if {$nOmit} {
+ puts "$nOmit jobs omitted due to failures$clreol"
+ }
+ }
+ if {$cls} {
+ # Clear everything else to the bottom of the screen
+ puts -nonewline "\033\[0J"
+ flush stdout
+ }
+ $db eval COMMIT
+}
+
+
+
+#--------------------------------------------------------------------------
+# Check if this is the "status" command:
+#
+if {[llength $argv]>=1
+ && [string compare -nocase status [lindex $argv 0]]==0
+} {
+ set delay 0
+ set cls 0
+ for {set ii 1} {$ii<[llength $argv]} {incr ii} {
+ set a0 [lindex $argv $ii]
+ if {$a0=="-d" && $ii+1<[llength $argv]} {
+ incr ii
+ set delay [lindex $argv $ii]
+ if {![string is integer -strict $delay]} {
+ puts "Argument to -d should be an integer"
+ exit 1
+ }
+ } elseif {$a0=="-cls" || $a0=="--cls"} {
+ set cls 1
+ } else {
+ puts "unknown option: \"$a0\""
+ exit 1
+ }
+ }
+
+ if {![file readable $TRG(dbname)]} {
+ puts "Database missing: $TRG(dbname)"
+ exit
+ }
+ sqlite3 mydb $TRG(dbname)
+ mydb timeout 2000
+
+ # Clear the whole screen initially.
+ #
+ if {$delay>0 || $cls} {puts -nonewline "\033\[2J"}
+
+ while {1} {
+ show_status mydb [expr {$delay>0 || $cls}]
+ if {$delay<=0} break
+ after [expr {$delay*1000}]
}
-
mydb close
exit
}
+# Scan the output of all jobs looking for the summary lines that
+# report the number of test cases and the number of errors.
+# Aggregate these numbers and return them.
+#
+proc aggregate_test_counts {db} {
+ set ncase 0
+ set nerr 0
+ $db eval {SELECT output FROM jobs WHERE displaytype IN ('tcl','fuzz')} {
+ set n 0
+ set m 0
+ if {[regexp {(\d+) errors out of (\d+) tests} $output all n m]
+ && [string is integer -strict $n]
+ && [string is integer -strict $m]} {
+ incr ncase $m
+ incr nerr $n
+ } elseif {[regexp {sessionfuzz.*: *(\d+) cases, (\d+) crash} $output \
+ all m n]
+ && [string is integer -strict $m]
+ && [string is integer -strict $n]} {
+ incr ncase $m
+ incr nerr $n
+ }
+ }
+ return [list $nerr $ncase]
+}
+
+#--------------------------------------------------------------------------
+# Check if this is the "errors" command:
+#
+if {[llength $argv]>=1 && [llength $argv]<=2
+ && ([string compare -nocase errors [lindex $argv 0]]==0 ||
+ [string match err* [lindex $argv 0]]==1)
+} {
+ set verbose 0
+ for {set ii 1} {$ii<[llength $argv]} {incr ii} {
+ set a0 [lindex $argv $ii]
+ if {$a0=="-v" || $a0=="--verbose" || $a0=="-verbose"} {
+ set verbose 1
+ } else {
+ puts "unknown option: \"$a0\"". Use --help for more info."
+ exit 1
+ }
+ }
+ set cnt 0
+ sqlite3 mydb $TRG(dbname)
+ mydb timeout 2000
+ mydb eval {SELECT displaytype, displayname, output
+ FROM jobs WHERE state='failed'} {
+ puts "**** $displayname ****"
+ if {$verbose || $displaytype!="tcl"} {
+ puts $output
+ } else {
+ foreach line [split $output \n] {
+ if {[string match {!*} $line] || [string match *failed* $line]} {
+ puts $line
+ }
+ }
+ }
+ incr cnt
+ }
+ set summary [aggregate_test_counts mydb]
+ mydb close
+ puts "Total [lindex $summary 0] errors out of [lindex $summary 1] tests"
+ exit
+}
+
#-------------------------------------------------------------------------
# Parse the command line.
#
@@ -433,8 +613,30 @@ for {set ii 0} {$ii < [llength $argv]} {incr ii} {
if {$isLast} { usage }
} elseif {($n>2 && [string match "$a*" --buildonly]) || $a=="-b"} {
set TRG(buildonly) 1
+ } elseif {($n>2 && [string match "$a*" --config]) || $a=="-c"} {
+ incr ii
+ set TRG(config) [lindex $argv $ii]
} elseif {($n>2 && [string match "$a*" --dryrun]) || $a=="-d"} {
set TRG(dryrun) 1
+ } elseif {($n>2 && [string match "$a*" --explain]) || $a=="-e"} {
+ set TRG(explain) 1
+ } elseif {($n>2 && [string match "$a*" --omit]) || $a=="-c"} {
+ incr ii
+ set TRG(omitconfig) [lindex $argv $ii]
+ } elseif {[string match "$a*" --stop-on-error]} {
+ set TRG(stopOnError) 1
+ } elseif {[string match "$a*" --stop-on-coredump]} {
+ set TRG(stopOnCore) 1
+ } elseif {[string match "$a*" --status]} {
+ if {$tcl_platform(platform)=="windows"} {
+ puts stdout \
+"The --status option is not available on Windows. A suggested work-around"
+ puts stdout \
+"is to run the following command in a separate window:\n"
+ puts stdout " [info nameofexe] $argv0 status -d 2\n"
+ } else {
+ set TRG(fullstatus) 1
+ }
} else {
usage
}
@@ -444,8 +646,6 @@ for {set ii 0} {$ii < [llength $argv]} {incr ii} {
}
set argv [list]
-
-
# This script runs individual tests - tcl scripts or [make xyz] commands -
# in directories named "testdir$N", where $N is an integer. This variable
# contains a list of integers indicating the directories in use.
@@ -550,12 +750,6 @@ proc r_get_next_job {iJob} {
return $ret
}
-#rename r_get_next_job r_get_next_job_r
-#proc r_get_next_job {iJob} {
- #puts [time { set res [r_get_next_job_r $iJob] }]
- #set res
-#}
-
# Usage:
#
# add_job OPTION ARG OPTION ARG...
@@ -617,7 +811,16 @@ proc add_job {args} {
trdb last_insert_rowid
}
-proc add_tcl_jobs {build config patternlist} {
+# Argument $build is either an empty string, or else a list of length 3
+# describing the job to build testfixture. In the usual form:
+#
+# {ID DIRNAME DISPLAYNAME}
+#
+# e.g
+#
+# {1 /home/user/sqlite/test/testrunner_bld_xyz All-Debug}
+#
+proc add_tcl_jobs {build config patternlist {shelldepid ""}} {
global TRG
set topdir [file dirname $::testdir]
@@ -666,34 +869,59 @@ proc add_tcl_jobs {build config patternlist} {
if {[lsearch $lProp slow]>=0} { set priority 2 }
if {[lsearch $lProp superslow]>=0} { set priority 4 }
+ set depid [lindex $build 0]
+ if {$shelldepid!="" && [lsearch $lProp shell]>=0} { set depid $shelldepid }
+
add_job \
-displaytype tcl \
-displayname $displayname \
-cmd $cmd \
- -depid [lindex $build 0] \
+ -depid $depid \
-priority $priority
-
}
}
-proc add_build_job {buildname target} {
+proc add_build_job {buildname target {postcmd ""} {depid ""}} {
global TRG
set dirname "[string tolower [string map {- _} $buildname]]_$target"
set dirname "testrunner_bld_$dirname"
+ set cmd "$TRG(makecmd) $target"
+ if {$postcmd!=""} {
+ append cmd "\n"
+ append cmd $postcmd
+ }
+
set id [add_job \
-displaytype bld \
-displayname "Build $buildname ($target)" \
-dirname $dirname \
-build $buildname \
- -cmd "$TRG(makecmd) $target" \
+ -cmd $cmd \
+ -depid $depid \
-priority 3
]
list $id [file normalize $dirname] $buildname
}
+proc add_shell_build_job {buildname dirname depid} {
+ global TRG
+
+ if {$TRG(platform)=="win"} {
+ set path [string map {/ \\} "$dirname/"]
+ set copycmd "xcopy $TRG(shell) $path"
+ } else {
+ set copycmd "cp $TRG(shell) $dirname/"
+ }
+
+ return [
+ add_build_job $buildname $TRG(shell) $copycmd $depid
+ ]
+}
+
+
proc add_make_job {bld target} {
global TRG
@@ -767,10 +995,30 @@ proc add_devtest_jobs {lBld patternlist} {
foreach b $lBld {
set bld [add_build_job $b $TRG(testfixture)]
- add_tcl_jobs $bld veryquick $patternlist
+ add_tcl_jobs $bld veryquick $patternlist SHELL
if {$patternlist==""} {
add_fuzztest_jobs $b
}
+
+ if {[trdb one "SELECT EXISTS (SELECT 1 FROM jobs WHERE depid='SHELL')"]} {
+ set sbld [add_shell_build_job $b [lindex $bld 1] [lindex $bld 0]]
+ set sbldid [lindex $sbld 0]
+ trdb eval {
+ UPDATE jobs SET depid=$sbldid WHERE depid='SHELL'
+ }
+ }
+
+ }
+}
+
+# Check to ensure that the interpreter is a full-blown "testfixture"
+# build and not just a "tclsh". If this is not the case, issue an
+# error message and exit.
+#
+proc must_be_testfixture {} {
+ if {[lsearch [info commands] sqlite3_soft_heap_limit]<0} {
+ puts "Use testfixture, not tclsh, for these arguments."
+ exit 1
}
}
@@ -789,6 +1037,7 @@ proc add_jobs_from_cmdline {patternlist} {
set first [lindex $patternlist 0]
switch -- $first {
all {
+ must_be_testfixture
set patternlist [lrange $patternlist 1 end]
set clist [trd_all_configs]
foreach c $clist {
@@ -797,16 +1046,26 @@ proc add_jobs_from_cmdline {patternlist} {
}
mdevtest {
- add_devtest_jobs {All-O0 All-Debug} [lrange $patternlist 1 end]
+ set config_set {
+ All-O0
+ All-Debug
+ }
+ add_devtest_jobs $config_set [lrange $patternlist 1 end]
}
sdevtest {
- add_devtest_jobs {All-Sanitize All-Debug} [lrange $patternlist 1 end]
+ set config_set {
+ All-Sanitize
+ All-Debug
+ }
+ add_devtest_jobs $config_set [lrange $patternlist 1 end]
}
release {
set patternlist [lrange $patternlist 1 end]
foreach b [trd_builds $TRG(platform)] {
+ if {$TRG(config)!="" && ![regexp "\\y$b\\y" $TRG(config)]} continue
+ if {[regexp "\\y$b\\y" $TRG(omitconfig)]} continue
set bld [add_build_job $b $TRG(testfixture)]
foreach c [trd_configs $TRG(platform) $b] {
add_tcl_jobs $bld $c $patternlist
@@ -824,7 +1083,15 @@ proc add_jobs_from_cmdline {patternlist} {
}
}
+ list {
+ set allperm [array names ::testspec]
+ lappend allperm all mdevtest sdevtest release list
+ puts "Allowed values for the PERMUTATION argument: [lsort $allperm]"
+ exit 0
+ }
+
default {
+ must_be_testfixture
if {[info exists ::testspec($first)]} {
add_tcl_jobs "" $first [lrange $patternlist 1 end]
} else {
@@ -837,6 +1104,7 @@ proc add_jobs_from_cmdline {patternlist} {
proc make_new_testset {} {
global TRG
+ trdb eval {PRAGMA journal_mode=WAL;}
r_write_db {
trdb eval $TRG(schema)
set nJob $TRG(nJob)
@@ -853,11 +1121,16 @@ proc make_new_testset {} {
proc mark_job_as_finished {jobid output state endtm} {
r_write_db {
+ if {$state=="failed"} {
+ set childstate omit
+ } else {
+ set childstate ready
+ }
trdb eval {
UPDATE jobs
SET output=$output, state=$state, endtime=$endtm
WHERE jobid=$jobid;
- UPDATE jobs SET state='ready' WHERE depid=$jobid;
+ UPDATE jobs SET state=$childstate WHERE depid=$jobid;
}
}
}
@@ -888,6 +1161,14 @@ proc script_input_ready {fd iJob jobid} {
}
puts "FAILED: $job(displayname) ($iJob)"
set state "failed"
+ if {$TRG(stopOnError)} {
+ puts "OUTPUT: $O($iJob)"
+ exit 1
+ }
+ if {$TRG(stopOnCore) && [string first {core dumped} $O($iJob)]>0} {
+ puts "OUTPUT: $O($iJob)"
+ exit 1
+ }
}
set tm [clock_milliseconds]
@@ -948,6 +1229,16 @@ proc launch_another_job {iJob} {
close $fd
}
+ # Add a batch/shell file command to set the directory used for temp
+ # files to the test's working directory. Otherwise, tests that use
+ # large numbers of temp files (e.g. zipvfs), might generate temp
+ # filename collisions.
+ if {$TRG(platform)=="win"} {
+ set set_tmp_dir "SET SQLITE_TMPDIR=[file normalize $dir]"
+ } else {
+ set set_tmp_dir "export SQLITE_TMPDIR=\"[file normalize $dir]\""
+ }
+
if { $TRG(dryrun) } {
mark_job_as_finished $job(jobid) "" done 0
@@ -962,61 +1253,71 @@ proc launch_another_job {iJob} {
set pwd [pwd]
cd $dir
set fd [open $TRG(run) w]
- puts $fd $job(cmd)
+ puts $fd $set_tmp_dir
+ puts $fd $job(cmd)
close $fd
set fd [open "|$TRG(runcmd) 2>@1" r]
cd $pwd
- fconfigure $fd -blocking false
+ fconfigure $fd -blocking false -translation binary
fileevent $fd readable [list script_input_ready $fd $iJob $job(jobid)]
}
return 1
}
-proc one_line_report {} {
+# Show the testing progress report
+#
+proc progress_report {} {
global TRG
- set tm [expr [clock_milliseconds] - $TRG(starttime)]
- set tm [format "%d" [expr int($tm/1000.0 + 0.5)]]
-
- r_write_db {
- trdb eval {
- SELECT displaytype, state, count(*) AS cnt
- FROM jobs
- GROUP BY 1, 2
- } {
- set v($state,$displaytype) $cnt
- incr t($displaytype) $cnt
+ if {$TRG(fullstatus)} {
+ if {$::tcl_platform(platform)=="windows"} {
+ exec [info nameofexe] $::argv0 status --cls
+ } else {
+ show_status trdb 1
}
- }
-
- set text ""
- foreach j [lsort [array names t]] {
- foreach k {done failed running} { incr v($k,$j) 0 }
- set fin [expr $v(done,$j) + $v(failed,$j)]
- lappend text "${j}($fin/$t($j))"
- if {$v(failed,$j)>0} {
- lappend text "f$v(failed,$j)"
+ } else {
+ set tm [expr [clock_milliseconds] - $TRG(starttime)]
+ set tm [format "%d" [expr int($tm/1000.0 + 0.5)]]
+
+ r_write_db {
+ trdb eval {
+ SELECT displaytype, state, count(*) AS cnt
+ FROM jobs
+ GROUP BY 1, 2
+ } {
+ set v($state,$displaytype) $cnt
+ incr t($displaytype) $cnt
+ }
}
- if {$v(running,$j)>0} {
- lappend text "r$v(running,$j)"
+
+ set text ""
+ foreach j [lsort [array names t]] {
+ foreach k {done failed running} { incr v($k,$j) 0 }
+ set fin [expr $v(done,$j) + $v(failed,$j)]
+ lappend text "${j}($fin/$t($j))"
+ if {$v(failed,$j)>0} {
+ lappend text "f$v(failed,$j)"
+ }
+ if {$v(running,$j)>0} {
+ lappend text "r$v(running,$j)"
+ }
+ }
+
+ if {[info exists TRG(reportlength)]} {
+ puts -nonewline "[string repeat " " $TRG(reportlength)]\r"
+ }
+ set report "${tm} [join $text { }]"
+ set TRG(reportlength) [string length $report]
+ if {[string length $report]<100} {
+ puts -nonewline "$report\r"
+ flush stdout
+ } else {
+ puts $report
}
}
-
- if {[info exists TRG(reportlength)]} {
- puts -nonewline "[string repeat " " $TRG(reportlength)]\r"
- }
- set report "${tm} [join $text { }]"
- set TRG(reportlength) [string length $report]
- if {[string length $report]<100} {
- puts -nonewline "$report\r"
- flush stdout
- } else {
- puts $report
- }
-
- after $TRG(reporttime) one_line_report
+ after $TRG(reporttime) progress_report
}
proc launch_some_jobs {} {
@@ -1041,13 +1342,14 @@ proc run_testset {} {
launch_some_jobs
- one_line_report
+ if {$TRG(fullstatus)} {puts "\033\[2J"}
+ progress_report
while {[dirs_nHelper]>0} {
after 500 {incr ::wakeup}
vwait ::wakeup
}
close $TRG(log)
- one_line_report
+ progress_report
r_write_db {
set tm [clock_milliseconds]
@@ -1061,6 +1363,10 @@ proc run_testset {} {
puts "FAILED: $displayname"
}
}
+ set nOmit [trdb one {SELECT count(*) FROM jobs WHERE state='omit'}]
+ if {$nOmit>0} {
+ puts "$nOmit jobs skipped due to prior failures"
+ }
}
puts "\nTest database is $TRG(dbname)"
@@ -1078,15 +1384,42 @@ proc handle_buildonly {} {
}
}
+# Handle the --explain option. Provide a human-readable
+# explanation of all the tests that are in the trdb database jobs
+# table.
+#
+proc explain_layer {indent depid} {
+ global TRG
+ if {$TRG(buildonly)} {
+ set showtests 0
+ } else {
+ set showtests 1
+ }
+ trdb eval {SELECT jobid, displayname, displaytype, dirname
+ FROM jobs WHERE depid=$depid ORDER BY displayname} {
+ if {$displaytype=="bld"} {
+ puts "${indent}$displayname in $dirname"
+ explain_layer "${indent} " $jobid
+ } elseif {$showtests} {
+ puts "${indent}[lindex $displayname end]"
+ }
+ }
+}
+proc explain_tests {} {
+ explain_layer "" ""
+}
+
sqlite3 trdb $TRG(dbname)
trdb timeout $TRG(timeout)
set tm [lindex [time { make_new_testset }] 0]
-if {$TRG(nJob)>1} {
- puts "splitting work across $TRG(nJob) jobs"
+if {$TRG(explain)} {
+ explain_tests
+} else {
+ if {$TRG(nJob)>1} {
+ puts "splitting work across $TRG(nJob) jobs"
+ }
+ puts "built testset in [expr $tm/1000]ms.."
+ handle_buildonly
+ run_testset
}
-puts "built testset in [expr $tm/1000]ms.."
-
-handle_buildonly
-run_testset
trdb close
-#puts [pwd]