2019-04-11 22:03:15 +03:00
|
|
|
#!/bin/sh
|
2019-04-09 22:53:32 +03:00
|
|
|
# \
|
|
|
|
exec wapptclsh "$0" ${1+"$@"}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
# package required wapp
|
|
|
|
source [file join [file dirname [info script]] wapp.tcl]
|
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
# Variables set by the "control" form:
|
|
|
|
#
|
|
|
|
# G(platform) - User selected platform.
|
2022-07-12 01:20:39 +03:00
|
|
|
# G(cfgglob) - Glob pattern that all configurations must match
|
2019-04-09 22:53:32 +03:00
|
|
|
# G(test) - Set to "Normal", "Veryquick", "Smoketest" or "Build-Only".
|
|
|
|
# G(keep) - Boolean. True to delete no files after each test.
|
|
|
|
# G(msvc) - Boolean. True to use MSVC as the compiler.
|
|
|
|
# G(tcl) - Use Tcl from this directory for builds.
|
|
|
|
# G(jobs) - How many sub-processes to run simultaneously.
|
|
|
|
#
|
|
|
|
set G(platform) $::tcl_platform(os)-$::tcl_platform(machine)
|
2022-07-12 13:46:02 +03:00
|
|
|
set G(cfgglob) *
|
2019-04-09 22:53:32 +03:00
|
|
|
set G(test) Normal
|
2019-05-01 18:25:38 +03:00
|
|
|
set G(keep) 1
|
2019-05-02 20:06:01 +03:00
|
|
|
set G(msvc) 0
|
2019-04-11 22:03:15 +03:00
|
|
|
set G(tcl) [::tcl::pkgconfig get libdir,install]
|
2019-04-09 22:53:32 +03:00
|
|
|
set G(jobs) 3
|
2019-04-11 22:03:15 +03:00
|
|
|
set G(debug) 0
|
2019-04-09 22:53:32 +03:00
|
|
|
|
2019-05-02 20:06:01 +03:00
|
|
|
set G(noui) 0
|
|
|
|
set G(stdout) 0
|
|
|
|
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
proc wapptest_init {} {
|
|
|
|
global G
|
2019-04-09 22:53:32 +03:00
|
|
|
|
2022-07-12 13:46:02 +03:00
|
|
|
set lSave [list platform test keep msvc tcl jobs debug noui stdout cfgglob]
|
2019-04-10 21:56:30 +03:00
|
|
|
foreach k $lSave { set A($k) $G($k) }
|
|
|
|
array unset G
|
|
|
|
foreach k $lSave { set G($k) $A($k) }
|
2019-04-09 22:53:32 +03:00
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
# The root of the SQLite source tree.
|
|
|
|
set G(srcdir) [file dirname [file dirname [info script]]]
|
2019-04-09 22:53:32 +03:00
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
set G(sqlite_version) "unknown"
|
2019-04-09 22:53:32 +03:00
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
# Either "config", "running" or "stopped":
|
|
|
|
set G(state) "config"
|
2019-04-10 22:45:19 +03:00
|
|
|
|
2019-04-11 22:03:15 +03:00
|
|
|
set G(hostname) "(unknown host)"
|
|
|
|
catch { set G(hostname) [exec hostname] }
|
|
|
|
set G(host) $G(hostname)
|
2019-04-10 22:45:19 +03:00
|
|
|
append G(host) " $::tcl_platform(os) $::tcl_platform(osVersion)"
|
|
|
|
append G(host) " $::tcl_platform(machine) $::tcl_platform(byteOrder)"
|
2019-04-10 21:56:30 +03:00
|
|
|
}
|
2019-04-09 22:53:32 +03:00
|
|
|
|
2019-05-02 20:06:01 +03:00
|
|
|
proc wapptest_run {} {
|
|
|
|
global G
|
|
|
|
set_test_array
|
|
|
|
set G(state) "running"
|
|
|
|
|
|
|
|
wapptest_openlog
|
|
|
|
|
|
|
|
wapptest_output "Running the following for $G(platform). $G(jobs) jobs."
|
|
|
|
foreach t $G(test_array) {
|
|
|
|
set config [dict get $t config]
|
|
|
|
set target [dict get $t target]
|
|
|
|
wapptest_output [format " %-25s%s" $config $target]
|
|
|
|
}
|
|
|
|
wapptest_output [string repeat * 70]
|
|
|
|
}
|
|
|
|
|
2019-08-01 00:08:55 +03:00
|
|
|
proc releasetest_data {args} {
|
|
|
|
global G
|
|
|
|
set rtd [file join $G(srcdir) test releasetest_data.tcl]
|
|
|
|
set fd [open "|[info nameofexecutable] $rtd $args" r+]
|
|
|
|
set ret [read $fd]
|
|
|
|
close $fd
|
|
|
|
return $ret
|
|
|
|
}
|
|
|
|
|
2019-04-30 23:43:10 +03:00
|
|
|
# Generate the text for the box at the top of the UI. The current SQLite
|
|
|
|
# version, according to fossil, along with a warning if there are
|
|
|
|
# uncommitted changes in the checkout.
|
2019-04-09 22:53:32 +03:00
|
|
|
#
|
2019-04-11 22:03:15 +03:00
|
|
|
proc generate_fossil_info {} {
|
|
|
|
global G
|
|
|
|
set pwd [pwd]
|
|
|
|
cd $G(srcdir)
|
2019-04-30 23:43:10 +03:00
|
|
|
set rc [catch {
|
|
|
|
set r1 [exec fossil info]
|
|
|
|
set r2 [exec fossil changes]
|
|
|
|
}]
|
2019-04-11 22:03:15 +03:00
|
|
|
cd $pwd
|
2019-04-30 23:43:10 +03:00
|
|
|
if {$rc} return
|
2019-04-11 22:03:15 +03:00
|
|
|
|
|
|
|
foreach line [split $r1 "\n"] {
|
|
|
|
if {[regexp {^checkout: *(.*)$} $line -> co]} {
|
|
|
|
wapp-trim { <br> %html($co) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if {[string trim $r2]!=""} {
|
|
|
|
wapp-trim {
|
|
|
|
<br><span class=warning>
|
|
|
|
WARNING: Uncommitted changes in checkout
|
|
|
|
</span>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
# If the application is in "config" state, set the contents of the
|
|
|
|
# ::G(test_array) global to reflect the tests that will be run. If the
|
|
|
|
# app is in some other state ("running" or "stopped"), this command
|
|
|
|
# is a no-op.
|
|
|
|
#
|
|
|
|
proc set_test_array {} {
|
|
|
|
global G
|
|
|
|
if { $G(state)=="config" } {
|
|
|
|
set G(test_array) [list]
|
2019-08-01 00:08:55 +03:00
|
|
|
set debug "-debug"
|
|
|
|
if {$G(debug)==0} { set debug "-nodebug"}
|
|
|
|
foreach {config target} [releasetest_data tests $debug $G(platform)] {
|
2019-04-09 22:53:32 +03:00
|
|
|
|
2022-07-12 01:20:39 +03:00
|
|
|
# All configuration names must match $g(cfgglob), which defaults to *
|
|
|
|
#
|
|
|
|
if {![string match -nocase $G(cfgglob) $config]} continue
|
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
# If using MSVC, do not run sanitize or valgrind tests. Or the
|
|
|
|
# checksymbols test.
|
|
|
|
if {$G(msvc) && (
|
|
|
|
"Sanitize" == $config
|
|
|
|
|| "checksymbols" in $target
|
|
|
|
|| "valgrindtest" in $target
|
|
|
|
)} {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
# If the test mode is not "Normal", override the target.
|
|
|
|
#
|
|
|
|
if {$target!="checksymbols" && $G(platform)!="Failure-Detection"} {
|
|
|
|
switch -- $G(test) {
|
|
|
|
Veryquick { set target quicktest }
|
|
|
|
Smoketest { set target smoketest }
|
|
|
|
Build-Only {
|
|
|
|
set target testfixture
|
|
|
|
if {$::tcl_platform(platform)=="windows"} {
|
|
|
|
set target testfixture.exe
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lappend G(test_array) [dict create config $config target $target]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
proc count_tests_and_errors {name logfile} {
|
|
|
|
global G
|
|
|
|
|
|
|
|
set fd [open $logfile rb]
|
|
|
|
set seen 0
|
|
|
|
while {![eof $fd]} {
|
|
|
|
set line [gets $fd]
|
|
|
|
if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} {
|
|
|
|
incr G(test.$name.nError) $nerr
|
|
|
|
incr G(test.$name.nTest) $ntest
|
|
|
|
set seen 1
|
|
|
|
if {$nerr>0} {
|
|
|
|
set G(test.$name.errmsg) $line
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if {[regexp {runtime error: +(.*)} $line all msg]} {
|
|
|
|
# skip over "value is outside range" errors
|
2020-08-12 00:53:42 +03:00
|
|
|
if {[regexp {.* is outside the range of representable} $line]} {
|
2019-04-09 22:53:32 +03:00
|
|
|
# noop
|
|
|
|
} else {
|
|
|
|
incr G(test.$name.nError)
|
|
|
|
if {$G(test.$name.errmsg)==""} {
|
|
|
|
set G(test.$name.errmsg) $msg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if {[regexp {fatal error +(.*)} $line all msg]} {
|
|
|
|
incr G(test.$name.nError)
|
|
|
|
if {$G(test.$name.errmsg)==""} {
|
|
|
|
set G(test.$name.errmsg) $msg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
|
|
|
|
incr G(test.$name.nError)
|
|
|
|
if {$G(test.$name.errmsg)==""} {
|
|
|
|
set G(test.$name.errmsg) $all
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if {[regexp {^VERSION: 3\.\d+.\d+} $line]} {
|
|
|
|
set v [string range $line 9 end]
|
|
|
|
if {$G(sqlite_version) eq "unknown"} {
|
|
|
|
set G(sqlite_version) $v
|
|
|
|
} elseif {$G(sqlite_version) ne $v} {
|
|
|
|
set G(test.$name.errmsg) "version conflict: {$G(sqlite_version)} vs. {$v}"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $fd
|
|
|
|
if {$G(test) == "Build-Only"} {
|
|
|
|
incr G(test.$name.nTest)
|
|
|
|
if {$G(test.$name.nError)>0} {
|
|
|
|
set errmsg "Build failed"
|
|
|
|
}
|
|
|
|
} elseif {!$seen} {
|
|
|
|
set G(test.$name.errmsg) "Test did not complete"
|
|
|
|
if {[file readable core]} {
|
|
|
|
append G(test.$name.errmsg) " - core file exists"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-02 20:06:01 +03:00
|
|
|
proc wapptest_output {str} {
|
|
|
|
global G
|
|
|
|
if {$G(stdout)} { puts $str }
|
|
|
|
if {[info exists G(log)]} {
|
|
|
|
puts $G(log) $str
|
|
|
|
flush $G(log)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
proc wapptest_openlog {} {
|
|
|
|
global G
|
|
|
|
set G(log) [open wapptest-out.txt w+]
|
|
|
|
}
|
|
|
|
proc wapptest_closelog {} {
|
|
|
|
global G
|
|
|
|
close $G(log)
|
|
|
|
unset G(log)
|
|
|
|
}
|
|
|
|
|
|
|
|
proc format_seconds {seconds} {
|
|
|
|
set min [format %.2d [expr ($seconds / 60) % 60]]
|
|
|
|
set hr [format %.2d [expr $seconds / 3600]]
|
|
|
|
set sec [format %.2d [expr $seconds % 60]]
|
|
|
|
return "$hr:$min:$sec"
|
|
|
|
}
|
|
|
|
|
2019-05-01 18:25:38 +03:00
|
|
|
# This command is invoked once a slave process has finished running its
|
|
|
|
# tests, successfully or otherwise. Parameter $name is the name of the
|
|
|
|
# test, $rc the exit code returned by the slave process.
|
|
|
|
#
|
2019-04-10 21:56:30 +03:00
|
|
|
proc slave_test_done {name rc} {
|
|
|
|
global G
|
|
|
|
set G(test.$name.done) [clock seconds]
|
|
|
|
set G(test.$name.nError) 0
|
|
|
|
set G(test.$name.nTest) 0
|
|
|
|
set G(test.$name.errmsg) ""
|
|
|
|
if {$rc} {
|
|
|
|
incr G(test.$name.nError)
|
|
|
|
}
|
|
|
|
if {[file exists $G(test.$name.log)]} {
|
|
|
|
count_tests_and_errors $name $G(test.$name.log)
|
|
|
|
}
|
2019-05-01 18:25:38 +03:00
|
|
|
|
|
|
|
# If the "keep files" checkbox is clear, delete all files except for
|
|
|
|
# the executables and test logs. And any core file that is present.
|
|
|
|
if {$G(keep)==0} {
|
|
|
|
set keeplist {
|
|
|
|
testfixture testfixture.exe
|
|
|
|
sqlite3 sqlite3.exe
|
|
|
|
test.log test-out.txt
|
|
|
|
core
|
2019-05-01 20:32:36 +03:00
|
|
|
wapptest_make.sh
|
|
|
|
wapptest_configure.sh
|
|
|
|
wapptest_run.tcl
|
2019-05-01 18:25:38 +03:00
|
|
|
}
|
|
|
|
foreach f [glob -nocomplain [file join $G(test.$name.dir) *]] {
|
|
|
|
set t [file tail $f]
|
|
|
|
if {[lsearch $keeplist $t]<0} {
|
|
|
|
catch { file delete -force $f }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-02 20:06:01 +03:00
|
|
|
|
|
|
|
# Format a message regarding the success or failure of hte test.
|
|
|
|
set t [format_seconds [expr $G(test.$name.done) - $G(test.$name.start)]]
|
|
|
|
set res "OK"
|
|
|
|
if {$G(test.$name.nError)} { set res "FAILED" }
|
|
|
|
set dots [string repeat . [expr 60 - [string length $name]]]
|
|
|
|
set msg "$name $dots $res ($t)"
|
|
|
|
|
|
|
|
wapptest_output $msg
|
|
|
|
if {[info exists G(test.$name.errmsg)] && $G(test.$name.errmsg)!=""} {
|
2019-07-04 19:30:41 +03:00
|
|
|
wapptest_output " $G(test.$name.errmsg)"
|
2019-05-02 20:06:01 +03:00
|
|
|
}
|
2019-04-10 21:56:30 +03:00
|
|
|
}
|
|
|
|
|
2019-05-01 18:25:38 +03:00
|
|
|
# This is a fileevent callback invoked each time a file-descriptor that
|
|
|
|
# connects this process to a slave process is readable.
|
|
|
|
#
|
2019-04-09 22:53:32 +03:00
|
|
|
proc slave_fileevent {name} {
|
|
|
|
global G
|
|
|
|
set fd $G(test.$name.channel)
|
|
|
|
|
|
|
|
if {[eof $fd]} {
|
|
|
|
fconfigure $fd -blocking 1
|
|
|
|
set rc [catch { close $fd }]
|
|
|
|
unset G(test.$name.channel)
|
2019-04-10 21:56:30 +03:00
|
|
|
slave_test_done $name $rc
|
2019-04-09 22:53:32 +03:00
|
|
|
} else {
|
|
|
|
set line [gets $fd]
|
|
|
|
if {[string trim $line] != ""} { puts "Trace : $name - \"$line\"" }
|
|
|
|
}
|
|
|
|
|
|
|
|
do_some_stuff
|
|
|
|
}
|
|
|
|
|
2019-05-01 18:25:38 +03:00
|
|
|
# Return the contents of the "slave script" - the script run by slave
|
2019-08-01 18:18:51 +03:00
|
|
|
# processes to actually perform the test. All it does is execute the
|
|
|
|
# test script already written to disk (wapptest_cmd.sh or wapptest_cmd.bat).
|
2019-05-01 18:25:38 +03:00
|
|
|
#
|
2019-04-30 23:43:10 +03:00
|
|
|
proc wapptest_slave_script {} {
|
|
|
|
global G
|
2019-08-01 00:08:55 +03:00
|
|
|
if {$G(msvc)==0} {
|
|
|
|
set dir [file join .. $G(srcdir)]
|
|
|
|
set res [subst -nocommands {
|
|
|
|
set rc [catch "exec sh wapptest_cmd.sh {$dir} >>& test.log" ]
|
|
|
|
exit [set rc]
|
|
|
|
}]
|
|
|
|
} else {
|
|
|
|
set dir [file nativename [file normalize $G(srcdir)]]
|
|
|
|
set dir [string map [list "\\" "\\\\"] $dir]
|
|
|
|
set res [subst -nocommands {
|
|
|
|
set rc [catch "exec wapptest_cmd.bat {$dir} >>& test.log" ]
|
|
|
|
exit [set rc]
|
|
|
|
}]
|
2019-04-30 23:43:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
set res
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Launch a slave process to run a test.
|
|
|
|
#
|
2019-08-01 00:08:55 +03:00
|
|
|
proc slave_launch {name target dir} {
|
2019-04-30 23:43:10 +03:00
|
|
|
global G
|
|
|
|
|
|
|
|
catch { file mkdir $dir } msg
|
|
|
|
foreach f [glob -nocomplain [file join $dir *]] {
|
|
|
|
catch { file delete -force $f }
|
|
|
|
}
|
2019-05-01 18:25:38 +03:00
|
|
|
set G(test.$name.dir) $dir
|
2019-04-30 23:43:10 +03:00
|
|
|
|
2019-08-01 00:08:55 +03:00
|
|
|
# Write the test command to wapptest_cmd.sh|bat.
|
2019-04-30 23:43:10 +03:00
|
|
|
#
|
2019-08-01 00:08:55 +03:00
|
|
|
set ext sh
|
|
|
|
if {$G(msvc)} { set ext bat }
|
|
|
|
set fd1 [open [file join $dir wapptest_cmd.$ext] w]
|
|
|
|
if {$G(msvc)} {
|
|
|
|
puts $fd1 [releasetest_data script -msvc $name $target]
|
|
|
|
} else {
|
|
|
|
puts $fd1 [releasetest_data script $name $target]
|
2019-04-30 23:43:10 +03:00
|
|
|
}
|
|
|
|
close $fd1
|
|
|
|
|
|
|
|
# Write the wapptest_run.tcl script to the test directory. To run the
|
|
|
|
# commands in the other two files.
|
|
|
|
#
|
|
|
|
set fd3 [open [file join $dir wapptest_run.tcl] w]
|
|
|
|
puts $fd3 [wapptest_slave_script]
|
|
|
|
close $fd3
|
|
|
|
|
|
|
|
set pwd [pwd]
|
|
|
|
cd $dir
|
|
|
|
set fd [open "|[info nameofexecutable] wapptest_run.tcl" r+]
|
|
|
|
cd $pwd
|
|
|
|
|
|
|
|
set G(test.$name.channel) $fd
|
|
|
|
fconfigure $fd -blocking 0
|
|
|
|
fileevent $fd readable [list slave_fileevent $name]
|
|
|
|
}
|
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
proc do_some_stuff {} {
|
|
|
|
global G
|
|
|
|
|
|
|
|
# Count the number of running jobs. A running job has an entry named
|
|
|
|
# "channel" in its dictionary.
|
|
|
|
set nRunning 0
|
|
|
|
set bFinished 1
|
|
|
|
foreach j $G(test_array) {
|
|
|
|
set name [dict get $j config]
|
|
|
|
if { [info exists G(test.$name.channel)]} { incr nRunning }
|
|
|
|
if {![info exists G(test.$name.done)]} { set bFinished 0 }
|
|
|
|
}
|
|
|
|
|
|
|
|
if {$bFinished} {
|
|
|
|
set nError 0
|
|
|
|
set nTest 0
|
|
|
|
set nConfig 0
|
|
|
|
foreach j $G(test_array) {
|
|
|
|
set name [dict get $j config]
|
|
|
|
incr nError $G(test.$name.nError)
|
|
|
|
incr nTest $G(test.$name.nTest)
|
|
|
|
incr nConfig
|
|
|
|
}
|
|
|
|
set G(result) "$nError errors from $nTest tests in $nConfig configurations."
|
2019-05-02 20:06:01 +03:00
|
|
|
wapptest_output [string repeat * 70]
|
|
|
|
wapptest_output $G(result)
|
2019-04-09 22:53:32 +03:00
|
|
|
catch {
|
|
|
|
append G(result) " SQLite version $G(sqlite_version)"
|
2019-05-02 20:06:01 +03:00
|
|
|
wapptest_output " SQLite version $G(sqlite_version)"
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
2019-04-10 21:56:30 +03:00
|
|
|
set G(state) "stopped"
|
2019-05-02 20:06:01 +03:00
|
|
|
wapptest_closelog
|
|
|
|
if {$G(noui)} { exit 0 }
|
2019-04-09 22:53:32 +03:00
|
|
|
} else {
|
|
|
|
set nLaunch [expr $G(jobs) - $nRunning]
|
|
|
|
foreach j $G(test_array) {
|
|
|
|
if {$nLaunch<=0} break
|
|
|
|
set name [dict get $j config]
|
|
|
|
if { ![info exists G(test.$name.channel)]
|
|
|
|
&& ![info exists G(test.$name.done)]
|
|
|
|
} {
|
2019-04-30 23:43:10 +03:00
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
set target [dict get $j target]
|
2019-08-01 00:08:55 +03:00
|
|
|
set dir [string tolower [string map {" " _ "-" _} $name]]
|
2019-04-09 22:53:32 +03:00
|
|
|
set G(test.$name.start) [clock seconds]
|
2019-08-01 00:08:55 +03:00
|
|
|
set G(test.$name.log) [file join $dir test.log]
|
2019-04-11 22:03:15 +03:00
|
|
|
|
2019-08-01 00:08:55 +03:00
|
|
|
slave_launch $name $target $dir
|
2019-04-30 23:43:10 +03:00
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
incr nLaunch -1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
proc generate_select_widget {label id lOpt opt} {
|
|
|
|
wapp-trim {
|
|
|
|
<label> %string($label) </label>
|
|
|
|
<select id=%string($id) name=%string($id)>
|
|
|
|
}
|
|
|
|
foreach o $lOpt {
|
|
|
|
set selected ""
|
|
|
|
if {$o==$opt} { set selected " selected=1" }
|
|
|
|
wapp-subst "<option $selected>$o</option>"
|
|
|
|
}
|
|
|
|
wapp-trim { </select> }
|
|
|
|
}
|
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
proc generate_main_page {{extra {}}} {
|
|
|
|
global G
|
|
|
|
set_test_array
|
|
|
|
|
2019-04-11 22:03:15 +03:00
|
|
|
set hostname $G(hostname)
|
2019-04-09 22:53:32 +03:00
|
|
|
wapp-trim {
|
|
|
|
<html>
|
|
|
|
<head>
|
2019-04-11 22:03:15 +03:00
|
|
|
<title> %html($hostname): wapptest.tcl </title>
|
2019-04-09 22:53:32 +03:00
|
|
|
<link rel="stylesheet" type="text/css" href="style.css"/>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
}
|
|
|
|
|
2019-04-10 22:45:19 +03:00
|
|
|
set host $G(host)
|
2019-04-09 22:53:32 +03:00
|
|
|
wapp-trim {
|
2019-04-11 22:03:15 +03:00
|
|
|
<div class="border">%string($host)
|
|
|
|
}
|
|
|
|
generate_fossil_info
|
|
|
|
wapp-trim {
|
|
|
|
</div>
|
|
|
|
<div class="border" id=controls>
|
|
|
|
<form action="control" method="post" name="control">
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
2019-04-10 21:56:30 +03:00
|
|
|
|
|
|
|
# Build the "platform" select widget.
|
2019-08-01 00:08:55 +03:00
|
|
|
set lOpt [releasetest_data platforms]
|
2019-04-10 21:56:30 +03:00
|
|
|
generate_select_widget Platform control_platform $lOpt $G(platform)
|
|
|
|
|
|
|
|
# Build the "test" select widget.
|
|
|
|
set lOpt [list Normal Veryquick Smoketest Build-Only]
|
|
|
|
generate_select_widget Test control_test $lOpt $G(test)
|
|
|
|
|
|
|
|
# Build the "jobs" select widget. Options are 1 to 8.
|
2022-11-04 20:07:33 +03:00
|
|
|
generate_select_widget Jobs control_jobs {1 2 3 4 5 6 7 8 12 16} $G(jobs)
|
2019-04-10 21:56:30 +03:00
|
|
|
|
|
|
|
switch $G(state) {
|
|
|
|
config {
|
|
|
|
set txt "Run Tests!"
|
|
|
|
set id control_run
|
|
|
|
}
|
|
|
|
running {
|
|
|
|
set txt "STOP Tests!"
|
|
|
|
set id control_stop
|
|
|
|
}
|
|
|
|
stopped {
|
|
|
|
set txt "Reset!"
|
|
|
|
set id control_reset
|
|
|
|
}
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
wapp-trim {
|
2019-04-10 21:56:30 +03:00
|
|
|
<div class=right>
|
|
|
|
<input id=%string($id) name=%string($id) type=submit value="%string($txt)">
|
|
|
|
</input>
|
|
|
|
</div>
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
2019-04-10 21:56:30 +03:00
|
|
|
|
|
|
|
wapp-trim {
|
|
|
|
<br><br>
|
2019-04-09 22:53:32 +03:00
|
|
|
<label> Tcl: </label>
|
|
|
|
<input id="control_tcl" name="control_tcl"></input>
|
|
|
|
<label> Keep files: </label>
|
|
|
|
<input id="control_keep" name="control_keep" type=checkbox value=1>
|
|
|
|
</input>
|
|
|
|
<label> Use MSVC: </label>
|
|
|
|
<input id="control_msvc" name="control_msvc" type=checkbox value=1>
|
2019-04-11 22:03:15 +03:00
|
|
|
<label> Debug tests: </label>
|
|
|
|
<input id="control_debug" name="control_debug" type=checkbox value=1>
|
2019-04-09 22:53:32 +03:00
|
|
|
</input>
|
|
|
|
}
|
|
|
|
wapp-trim {
|
|
|
|
</form>
|
|
|
|
}
|
2019-04-10 21:56:30 +03:00
|
|
|
wapp-trim {
|
|
|
|
</div>
|
2019-04-11 22:03:15 +03:00
|
|
|
<div id=tests>
|
2019-04-10 21:56:30 +03:00
|
|
|
}
|
|
|
|
wapp-page-tests
|
|
|
|
|
|
|
|
set script "script/$G(state).js"
|
|
|
|
wapp-trim {
|
|
|
|
</div>
|
|
|
|
<script src=%string($script)></script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
proc wapp-default {} {
|
|
|
|
generate_main_page
|
|
|
|
}
|
|
|
|
|
|
|
|
proc wapp-page-tests {} {
|
|
|
|
global G
|
2019-04-11 22:03:15 +03:00
|
|
|
wapp-trim { <table class="border" width=100%> }
|
2019-04-09 22:53:32 +03:00
|
|
|
foreach t $G(test_array) {
|
|
|
|
set config [dict get $t config]
|
|
|
|
set target [dict get $t target]
|
|
|
|
|
|
|
|
set class "testwait"
|
|
|
|
set seconds ""
|
|
|
|
|
|
|
|
if {[info exists G(test.$config.log)]} {
|
|
|
|
if {[info exists G(test.$config.channel)]} {
|
|
|
|
set class "testrunning"
|
|
|
|
set seconds [expr [clock seconds] - $G(test.$config.start)]
|
|
|
|
} elseif {[info exists G(test.$config.done)]} {
|
|
|
|
if {$G(test.$config.nError)>0} {
|
|
|
|
set class "testfail"
|
|
|
|
} else {
|
|
|
|
set class "testdone"
|
|
|
|
}
|
|
|
|
set seconds [expr $G(test.$config.done) - $G(test.$config.start)]
|
|
|
|
}
|
2019-05-02 20:06:01 +03:00
|
|
|
set seconds [format_seconds $seconds]
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
wapp-trim {
|
|
|
|
<tr class=%string($class)>
|
2019-04-11 22:03:15 +03:00
|
|
|
<td class="nowrap"> %html($config)
|
|
|
|
<td class="padleft nowrap"> %html($target)
|
|
|
|
<td class="padleft nowrap"> %html($seconds)
|
|
|
|
<td class="padleft nowrap">
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
if {[info exists G(test.$config.log)]} {
|
|
|
|
set log $G(test.$config.log)
|
|
|
|
set uri "log/$log"
|
|
|
|
wapp-trim {
|
|
|
|
<a href=%url($uri)> %html($log) </a>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if {[info exists G(test.$config.errmsg)] && $G(test.$config.errmsg)!=""} {
|
|
|
|
set errmsg $G(test.$config.errmsg)
|
|
|
|
wapp-trim {
|
|
|
|
<tr class=testfail>
|
2019-04-11 22:03:15 +03:00
|
|
|
<td> <td class="padleft" colspan=3> %html($errmsg)
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
wapp-trim { </table> }
|
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
if {[info exists G(result)]} {
|
|
|
|
set res $G(result)
|
|
|
|
wapp-trim {
|
2019-04-10 21:56:30 +03:00
|
|
|
<div class=border id=result> %string($res) </div>
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
# URI: /control
|
|
|
|
#
|
|
|
|
# Whenever the form at the top of the application page is submitted, it
|
|
|
|
# is submitted here.
|
|
|
|
#
|
2019-04-09 22:53:32 +03:00
|
|
|
proc wapp-page-control {} {
|
|
|
|
global G
|
2019-04-10 21:56:30 +03:00
|
|
|
if {$::G(state)=="config"} {
|
2019-04-11 22:03:15 +03:00
|
|
|
set lControls [list platform test tcl jobs keep msvc debug]
|
2019-04-10 21:56:30 +03:00
|
|
|
set G(msvc) 0
|
|
|
|
set G(keep) 0
|
2019-04-11 22:03:15 +03:00
|
|
|
set G(debug) 0
|
2019-04-10 21:56:30 +03:00
|
|
|
} else {
|
|
|
|
set lControls [list jobs]
|
|
|
|
}
|
|
|
|
foreach v $lControls {
|
2019-04-09 22:53:32 +03:00
|
|
|
if {[wapp-param-exists control_$v]} {
|
|
|
|
set G($v) [wapp-param control_$v]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
if {[wapp-param-exists control_run]} {
|
|
|
|
# This is a "run test" command.
|
2019-05-02 20:06:01 +03:00
|
|
|
wapptest_run
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
if {[wapp-param-exists control_stop]} {
|
|
|
|
# A "STOP tests" command.
|
|
|
|
set G(state) "stopped"
|
|
|
|
set G(result) "Test halted by user"
|
|
|
|
foreach j $G(test_array) {
|
|
|
|
set name [dict get $j config]
|
|
|
|
if { [info exists G(test.$name.channel)] } {
|
|
|
|
close $G(test.$name.channel)
|
|
|
|
unset G(test.$name.channel)
|
|
|
|
slave_test_done $name 1
|
|
|
|
}
|
|
|
|
}
|
2019-05-02 20:06:01 +03:00
|
|
|
wapptest_closelog
|
2019-04-10 21:56:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if {[wapp-param-exists control_reset]} {
|
|
|
|
# A "reset app" command.
|
|
|
|
set G(state) "config"
|
|
|
|
wapptest_init
|
|
|
|
}
|
|
|
|
|
2019-04-09 22:53:32 +03:00
|
|
|
if {$::G(state) == "running"} {
|
|
|
|
do_some_stuff
|
|
|
|
}
|
|
|
|
wapp-redirect /
|
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
# URI: /style.css
|
|
|
|
#
|
|
|
|
# Return the stylesheet for the application main page.
|
|
|
|
#
|
2019-04-09 22:53:32 +03:00
|
|
|
proc wapp-page-style.css {} {
|
|
|
|
wapp-subst {
|
|
|
|
|
2019-04-11 22:03:15 +03:00
|
|
|
/* The boxes with black borders use this class */
|
2019-04-10 21:56:30 +03:00
|
|
|
.border {
|
|
|
|
border: 3px groove #444444;
|
|
|
|
padding: 1em;
|
|
|
|
margin-top: 1em;
|
|
|
|
margin-bottom: 1em;
|
|
|
|
}
|
|
|
|
|
2019-04-11 22:03:15 +03:00
|
|
|
/* Float to the right (used for the Run/Stop/Reset button) */
|
|
|
|
.right { float: right; }
|
2019-04-10 21:56:30 +03:00
|
|
|
|
2019-04-11 22:03:15 +03:00
|
|
|
/* Style for the large red warning at the top of the page */
|
2019-04-09 22:53:32 +03:00
|
|
|
.warning {
|
|
|
|
color: red;
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
|
2019-04-11 22:03:15 +03:00
|
|
|
/* Styles used by cells in the test table */
|
|
|
|
.padleft { padding-left: 5ex; }
|
|
|
|
.nowrap { white-space: nowrap; }
|
2019-04-10 21:56:30 +03:00
|
|
|
|
2019-04-11 22:03:15 +03:00
|
|
|
/* Styles for individual tests, depending on the outcome */
|
|
|
|
.testwait { }
|
|
|
|
.testrunning { color: blue }
|
|
|
|
.testdone { color: green }
|
|
|
|
.testfail { color: red }
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
# URI: /script/${state}.js
|
|
|
|
#
|
|
|
|
# The last part of this URI is always "config.js", "running.js" or
|
|
|
|
# "stopped.js", depending on the state of the application. It returns
|
|
|
|
# the javascript part of the front-end for the requested state to the
|
|
|
|
# browser.
|
|
|
|
#
|
|
|
|
proc wapp-page-script {} {
|
|
|
|
regexp {[^/]*$} [wapp-param REQUEST_URI] script
|
2019-04-09 22:53:32 +03:00
|
|
|
|
|
|
|
set tcl $::G(tcl)
|
|
|
|
set keep $::G(keep)
|
|
|
|
set msvc $::G(msvc)
|
2019-04-11 22:03:15 +03:00
|
|
|
set debug $::G(debug)
|
2019-04-09 22:53:32 +03:00
|
|
|
|
|
|
|
wapp-subst {
|
2019-04-10 21:56:30 +03:00
|
|
|
var lElem = \["control_platform", "control_test", "control_msvc",
|
2019-04-11 22:03:15 +03:00
|
|
|
"control_jobs", "control_debug"
|
2019-04-10 21:56:30 +03:00
|
|
|
\];
|
2019-04-09 22:53:32 +03:00
|
|
|
lElem.forEach(function(e) {
|
|
|
|
var elem = document.getElementById(e);
|
|
|
|
elem.addEventListener("change", function() { control.submit() } );
|
|
|
|
})
|
|
|
|
|
|
|
|
elem = document.getElementById("control_tcl");
|
|
|
|
elem.value = "%string($tcl)"
|
|
|
|
|
|
|
|
elem = document.getElementById("control_keep");
|
|
|
|
elem.checked = %string($keep);
|
|
|
|
|
|
|
|
elem = document.getElementById("control_msvc");
|
|
|
|
elem.checked = %string($msvc);
|
2019-04-11 22:03:15 +03:00
|
|
|
|
|
|
|
elem = document.getElementById("control_debug");
|
|
|
|
elem.checked = %string($debug);
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
if {$script != "config.js"} {
|
2019-04-09 22:53:32 +03:00
|
|
|
wapp-subst {
|
|
|
|
var lElem = \["control_platform", "control_test",
|
2019-04-12 16:40:54 +03:00
|
|
|
"control_tcl", "control_keep", "control_msvc",
|
|
|
|
"control_debug"
|
2019-04-09 22:53:32 +03:00
|
|
|
\];
|
|
|
|
lElem.forEach(function(e) {
|
|
|
|
var elem = document.getElementById(e);
|
|
|
|
elem.disabled = true;
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2019-04-10 21:56:30 +03:00
|
|
|
|
|
|
|
if {$script == "running.js"} {
|
|
|
|
wapp-subst {
|
|
|
|
function reload_tests() {
|
|
|
|
fetch('tests')
|
|
|
|
.then( data => data.text() )
|
|
|
|
.then( data => {
|
|
|
|
document.getElementById("tests").innerHTML = data;
|
|
|
|
})
|
|
|
|
.then( data => {
|
|
|
|
if( document.getElementById("result") ){
|
|
|
|
document.location = document.location;
|
|
|
|
} else {
|
|
|
|
setTimeout(reload_tests, 1000)
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(reload_tests, 1000)
|
|
|
|
}
|
|
|
|
}
|
2019-04-09 22:53:32 +03:00
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
# URI: /env
|
|
|
|
#
|
|
|
|
# This is for debugging only. Serves no other purpose.
|
|
|
|
#
|
2019-04-09 22:53:32 +03:00
|
|
|
proc wapp-page-env {} {
|
|
|
|
wapp-allow-xorigin-params
|
|
|
|
wapp-trim {
|
|
|
|
<h1>Wapp Environment</h1>\n<pre>
|
|
|
|
<pre>%html([wapp-debug-env])</pre>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-10 21:56:30 +03:00
|
|
|
# URI: /log/dirname/test.log
|
|
|
|
#
|
|
|
|
# This URI reads file "dirname/test.log" from disk, wraps it in a <pre>
|
|
|
|
# block, and returns it to the browser. Use for viewing log files.
|
|
|
|
#
|
2019-04-09 22:53:32 +03:00
|
|
|
proc wapp-page-log {} {
|
|
|
|
set log [string range [wapp-param REQUEST_URI] 5 end]
|
|
|
|
set fd [open $log]
|
|
|
|
set data [read $fd]
|
|
|
|
close $fd
|
|
|
|
wapp-trim {
|
|
|
|
<pre>
|
|
|
|
%html($data)
|
|
|
|
</pre>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-02 20:06:01 +03:00
|
|
|
# Print out a usage message. Then do [exit 1].
|
|
|
|
#
|
|
|
|
proc wapptest_usage {} {
|
|
|
|
puts stderr {
|
|
|
|
This Tcl script is used to test various configurations of SQLite. By
|
|
|
|
default it uses "wapp" to provide an interactive interface. Supported
|
|
|
|
command line options (all optional) are:
|
|
|
|
|
|
|
|
--platform PLATFORM (which tests to run)
|
2022-07-12 01:20:39 +03:00
|
|
|
--config GLOB (only run configurations matching GLOB)
|
2019-05-02 20:06:01 +03:00
|
|
|
--smoketest (run "make smoketest" only)
|
|
|
|
--veryquick (run veryquick.test only)
|
|
|
|
--buildonly (build executables, do not run tests)
|
|
|
|
--jobs N (number of concurrent jobs)
|
|
|
|
--tcl DIR (where to find tclConfig.sh)
|
|
|
|
--deletefiles (delete extra files after each test)
|
|
|
|
--msvc (Use MS Visual C)
|
|
|
|
--debug (Also run [n]debugging versions of tests)
|
|
|
|
--noui (do not use wapp)
|
|
|
|
}
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
# Sort command line arguments into two groups: those that belong to wapp,
|
|
|
|
# and those that belong to the application.
|
|
|
|
set WAPPARG(-server) 1
|
|
|
|
set WAPPARG(-local) 1
|
|
|
|
set WAPPARG(-scgi) 1
|
|
|
|
set WAPPARG(-remote-scgi) 1
|
|
|
|
set WAPPARG(-fromip) 1
|
|
|
|
set WAPPARG(-nowait) 0
|
|
|
|
set WAPPARG(-cgi) 0
|
|
|
|
set lWappArg [list]
|
|
|
|
set lTestArg [list]
|
|
|
|
for {set i 0} {$i < [llength $argv]} {incr i} {
|
|
|
|
set arg [lindex $argv $i]
|
|
|
|
if {[string range $arg 0 1]=="--"} {
|
|
|
|
set arg [string range $arg 1 end]
|
|
|
|
}
|
|
|
|
if {[info exists WAPPARG($arg)]} {
|
|
|
|
lappend lWappArg $arg
|
|
|
|
if {$WAPPARG($arg)} {
|
|
|
|
incr i
|
|
|
|
lappend lWappArg [lindex $argv $i]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lappend lTestArg $arg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-03 16:44:08 +03:00
|
|
|
wapptest_init
|
2019-05-02 20:06:01 +03:00
|
|
|
for {set i 0} {$i < [llength $lTestArg]} {incr i} {
|
2019-10-03 16:44:08 +03:00
|
|
|
set opt [lindex $lTestArg $i]
|
|
|
|
if {[string range $opt 0 1]=="--"} {
|
|
|
|
set opt [string range $opt 1 end]
|
|
|
|
}
|
|
|
|
switch -- $opt {
|
2019-05-02 20:06:01 +03:00
|
|
|
-platform {
|
|
|
|
if {$i==[llength $lTestArg]-1} { wapptest_usage }
|
|
|
|
incr i
|
|
|
|
set arg [lindex $lTestArg $i]
|
2019-08-01 00:08:55 +03:00
|
|
|
set lPlatform [releasetest_data platforms]
|
2019-05-02 20:06:01 +03:00
|
|
|
if {[lsearch $lPlatform $arg]<0} {
|
|
|
|
puts stderr "No such platform: $arg. Platforms are: $lPlatform"
|
|
|
|
exit -1
|
|
|
|
}
|
|
|
|
set G(platform) $arg
|
|
|
|
}
|
|
|
|
|
|
|
|
-smoketest { set G(test) Smoketest }
|
|
|
|
-veryquick { set G(test) Veryquick }
|
|
|
|
-buildonly { set G(test) Build-Only }
|
|
|
|
-jobs {
|
|
|
|
if {$i==[llength $lTestArg]-1} { wapptest_usage }
|
|
|
|
incr i
|
|
|
|
set G(jobs) [lindex $lTestArg $i]
|
|
|
|
}
|
|
|
|
|
|
|
|
-tcl {
|
|
|
|
if {$i==[llength $lTestArg]-1} { wapptest_usage }
|
|
|
|
incr i
|
|
|
|
set G(tcl) [lindex $lTestArg $i]
|
|
|
|
}
|
|
|
|
|
|
|
|
-deletefiles {
|
|
|
|
set G(keep) 0
|
|
|
|
}
|
|
|
|
|
|
|
|
-msvc {
|
|
|
|
set G(msvc) 1
|
|
|
|
}
|
|
|
|
|
|
|
|
-debug {
|
|
|
|
set G(debug) 1
|
|
|
|
}
|
|
|
|
|
|
|
|
-noui {
|
|
|
|
set G(noui) 1
|
|
|
|
set G(stdout) 1
|
|
|
|
}
|
|
|
|
|
2022-07-12 01:20:39 +03:00
|
|
|
-config {
|
|
|
|
if {$i==[llength $lTestArg]-1} { wapptest_usage }
|
|
|
|
incr i
|
|
|
|
set G(cfgglob) [lindex $lTestArg $i]
|
|
|
|
}
|
|
|
|
|
2019-05-02 20:06:01 +03:00
|
|
|
-stdout {
|
|
|
|
set G(stdout) 1
|
|
|
|
}
|
|
|
|
|
|
|
|
default {
|
|
|
|
puts stderr "Unrecognized option: [lindex $lTestArg $i]"
|
|
|
|
wapptest_usage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if {$G(noui)==0} {
|
|
|
|
wapp-start $lWappArg
|
|
|
|
} else {
|
|
|
|
wapptest_run
|
|
|
|
do_some_stuff
|
|
|
|
vwait forever
|
|
|
|
}
|