aboutsummaryrefslogtreecommitdiff
path: root/testdata/tcl/releasetest.tcl
diff options
context:
space:
mode:
authorJan Mercl <0xjnml@gmail.com>2020-07-26 22:36:18 +0200
committerJan Mercl <0xjnml@gmail.com>2020-07-26 22:36:18 +0200
commitb406626c64313ae348996c243a0a05d3f6ed2c3c (patch)
tree0eaae4fa6348b150568725e6f2ec0b4c4203b5f8 /testdata/tcl/releasetest.tcl
parentd8d9f40ce80062793349c0ea47520b6878312f4a (diff)
release v1.4.0-beta1v1.4.0-beta1
Diffstat (limited to 'testdata/tcl/releasetest.tcl')
-rw-r--r--testdata/tcl/releasetest.tcl1100
1 files changed, 1100 insertions, 0 deletions
diff --git a/testdata/tcl/releasetest.tcl b/testdata/tcl/releasetest.tcl
new file mode 100644
index 0000000..37f00eb
--- /dev/null
+++ b/testdata/tcl/releasetest.tcl
@@ -0,0 +1,1100 @@
+#!/usr/bin/tclsh
+#
+# Documentation for this script. This may be output to stderr
+# if the script is invoked incorrectly. See the [process_options]
+# proc below.
+#
+set ::USAGE_MESSAGE {
+This Tcl script is used to test the various configurations required
+before releasing a new version. Supported command line options (all
+optional) are:
+
+ --buildonly (Just build testfixture - do not run)
+ --config CONFIGNAME (Run only CONFIGNAME)
+ --dryrun (Print what would have happened)
+ -f|--force (Run even if uncommitted changes)
+ --info (Show diagnostic info)
+ --jobs N (Use N processes - default 1)
+ --keep (Delete no files after each test run)
+ --msvc (Use MSVC as the compiler)
+ --platform PLATFORM (see below)
+ --progress (Show progress messages)
+ --quick (Run "veryquick.test" only)
+ --veryquick (Run "make smoketest" only)
+ --with-tcl=DIR (Use TCL build at DIR)
+
+The script determines the default value for --platform using the
+$tcl_platform(os) and $tcl_platform(machine) variables. Supported
+platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386",
+"Darwin-x86_64", "Windows NT-intel", and "Windows NT-amd64".
+
+Every test begins with a fresh run of the configure script at the top
+of the SQLite source tree.
+}
+
+# Return a timestamp of the form HH:MM:SS
+#
+proc now {} {
+ return [clock format [clock seconds] -format %H:%M:%S]
+}
+
+# Omit comments (text between # and \n) in a long multi-line string.
+#
+proc strip_comments {in} {
+ regsub -all {#[^\n]*\n} $in {} out
+ return $out
+}
+
+array set ::Configs [strip_comments {
+ "Default" {
+ -O2
+ --disable-amalgamation --disable-shared
+ --enable-session
+ -DSQLITE_ENABLE_DESERIALIZE
+ }
+ "Sanitize" {
+ CC=clang -fsanitize=undefined
+ -DSQLITE_ENABLE_STAT4
+ --enable-session
+ }
+ "Stdcall" {
+ -DUSE_STDCALL=1
+ -O2
+ }
+ "Have-Not" {
+ # The "Have-Not" configuration sets all possible -UHAVE_feature options
+ # in order to verify that the code works even on platforms that lack
+ # these support services.
+ -DHAVE_FDATASYNC=0
+ -DHAVE_GMTIME_R=0
+ -DHAVE_ISNAN=0
+ -DHAVE_LOCALTIME_R=0
+ -DHAVE_LOCALTIME_S=0
+ -DHAVE_MALLOC_USABLE_SIZE=0
+ -DHAVE_STRCHRNUL=0
+ -DHAVE_USLEEP=0
+ -DHAVE_UTIME=0
+ }
+ "Unlock-Notify" {
+ -O2
+ -DSQLITE_ENABLE_UNLOCK_NOTIFY
+ -DSQLITE_THREADSAFE
+ -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
+ }
+ "User-Auth" {
+ -O2
+ -DSQLITE_USER_AUTHENTICATION=1
+ }
+ "Secure-Delete" {
+ -O2
+ -DSQLITE_SECURE_DELETE=1
+ -DSQLITE_SOUNDEX=1
+ }
+ "Update-Delete-Limit" {
+ -O2
+ -DSQLITE_DEFAULT_FILE_FORMAT=4
+ -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
+ -DSQLITE_ENABLE_STMT_SCANSTATUS
+ -DSQLITE_LIKE_DOESNT_MATCH_BLOBS
+ -DSQLITE_ENABLE_CURSOR_HINTS
+ --enable-json1
+ }
+ "Check-Symbols" {
+ -DSQLITE_MEMDEBUG=1
+ -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
+ -DSQLITE_ENABLE_FTS3=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_ENABLE_MEMSYS5=1
+ -DSQLITE_ENABLE_MEMSYS3=1
+ -DSQLITE_ENABLE_COLUMN_METADATA=1
+ -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
+ -DSQLITE_SECURE_DELETE=1
+ -DSQLITE_SOUNDEX=1
+ -DSQLITE_ENABLE_ATOMIC_WRITE=1
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
+ -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_ENABLE_STMT_SCANSTATUS
+ --enable-json1 --enable-fts5 --enable-session
+ }
+ "Debug-One" {
+ --disable-shared
+ -O2 -funsigned-char
+ -DSQLITE_DEBUG=1
+ -DSQLITE_MEMDEBUG=1
+ -DSQLITE_MUTEX_NOOP=1
+ -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
+ -DSQLITE_ENABLE_FTS3=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_ENABLE_MEMSYS5=1
+ -DSQLITE_ENABLE_COLUMN_METADATA=1
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_ENABLE_HIDDEN_COLUMNS
+ -DSQLITE_MAX_ATTACHED=125
+ -DSQLITE_MUTATION_TEST
+ --enable-fts5 --enable-json1
+ }
+ "Fast-One" {
+ -O6
+ -DSQLITE_ENABLE_FTS4=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_ENABLE_RBU
+ -DSQLITE_MAX_ATTACHED=125
+ -DLONGDOUBLE_TYPE=double
+ --enable-session
+ }
+ "Device-One" {
+ -O2
+ -DSQLITE_DEBUG=1
+ -DSQLITE_DEFAULT_AUTOVACUUM=1
+ -DSQLITE_DEFAULT_CACHE_SIZE=64
+ -DSQLITE_DEFAULT_PAGE_SIZE=1024
+ -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32
+ -DSQLITE_DISABLE_LFS=1
+ -DSQLITE_ENABLE_ATOMIC_WRITE=1
+ -DSQLITE_ENABLE_IOTRACE=1
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
+ -DSQLITE_MAX_PAGE_SIZE=4096
+ -DSQLITE_OMIT_LOAD_EXTENSION=1
+ -DSQLITE_OMIT_PROGRESS_CALLBACK=1
+ -DSQLITE_OMIT_VIRTUALTABLE=1
+ -DSQLITE_ENABLE_HIDDEN_COLUMNS
+ -DSQLITE_TEMP_STORE=3
+ --enable-json1
+ }
+ "Device-Two" {
+ -DSQLITE_4_BYTE_ALIGNED_MALLOC=1
+ -DSQLITE_DEFAULT_AUTOVACUUM=1
+ -DSQLITE_DEFAULT_CACHE_SIZE=1000
+ -DSQLITE_DEFAULT_LOCKING_MODE=0
+ -DSQLITE_DEFAULT_PAGE_SIZE=1024
+ -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=1000
+ -DSQLITE_DISABLE_LFS=1
+ -DSQLITE_ENABLE_FTS3=1
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_MAX_COMPOUND_SELECT=50
+ -DSQLITE_MAX_PAGE_SIZE=32768
+ -DSQLITE_OMIT_TRACE=1
+ -DSQLITE_TEMP_STORE=3
+ -DSQLITE_THREADSAFE=2
+ -DSQLITE_ENABLE_DESERIALIZE=1
+ --enable-json1 --enable-fts5 --enable-session
+ }
+ "Locking-Style" {
+ -O2
+ -DSQLITE_ENABLE_LOCKING_STYLE=1
+ }
+ "Apple" {
+ -Os
+ -DHAVE_GMTIME_R=1
+ -DHAVE_ISNAN=1
+ -DHAVE_LOCALTIME_R=1
+ -DHAVE_PREAD=1
+ -DHAVE_PWRITE=1
+ -DHAVE_USLEEP=1
+ -DHAVE_USLEEP=1
+ -DHAVE_UTIME=1
+ -DSQLITE_DEFAULT_CACHE_SIZE=1000
+ -DSQLITE_DEFAULT_CKPTFULLFSYNC=1
+ -DSQLITE_DEFAULT_MEMSTATUS=1
+ -DSQLITE_DEFAULT_PAGE_SIZE=1024
+ -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1
+ -DSQLITE_ENABLE_API_ARMOR=1
+ -DSQLITE_ENABLE_AUTO_PROFILE=1
+ -DSQLITE_ENABLE_FLOCKTIMEOUT=1
+ -DSQLITE_ENABLE_FTS3=1
+ -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
+ -DSQLITE_ENABLE_FTS3_TOKENIZER=1
+ if:os=="Darwin" -DSQLITE_ENABLE_LOCKING_STYLE=1
+ -DSQLITE_ENABLE_PERSIST_WAL=1
+ -DSQLITE_ENABLE_PURGEABLE_PCACHE=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_ENABLE_SNAPSHOT=1
+ # -DSQLITE_ENABLE_SQLLOG=1
+ -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
+ -DSQLITE_MAX_LENGTH=2147483645
+ -DSQLITE_MAX_VARIABLE_NUMBER=500000
+ # -DSQLITE_MEMDEBUG=1
+ -DSQLITE_NO_SYNC=1
+ -DSQLITE_OMIT_AUTORESET=1
+ -DSQLITE_OMIT_LOAD_EXTENSION=1
+ -DSQLITE_PREFER_PROXY_LOCKING=1
+ -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
+ -DSQLITE_THREADSAFE=2
+ -DSQLITE_USE_URI=1
+ -DSQLITE_WRITE_WALFRAME_PREBUFFERED=1
+ -DUSE_GUARDED_FD=1
+ -DUSE_PREAD=1
+ --enable-json1 --enable-fts5
+ }
+ "Extra-Robustness" {
+ -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
+ -DSQLITE_MAX_ATTACHED=62
+ }
+ "Devkit" {
+ -DSQLITE_DEFAULT_FILE_FORMAT=4
+ -DSQLITE_MAX_ATTACHED=30
+ -DSQLITE_ENABLE_COLUMN_METADATA
+ -DSQLITE_ENABLE_FTS4
+ -DSQLITE_ENABLE_FTS5
+ -DSQLITE_ENABLE_FTS4_PARENTHESIS
+ -DSQLITE_DISABLE_FTS4_DEFERRED
+ -DSQLITE_ENABLE_RTREE
+ --enable-json1 --enable-fts5
+ }
+ "No-lookaside" {
+ -DSQLITE_TEST_REALLOC_STRESS=1
+ -DSQLITE_OMIT_LOOKASIDE=1
+ -DHAVE_USLEEP=1
+ }
+ "Valgrind" {
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_ENABLE_FTS4
+ -DSQLITE_ENABLE_RTREE
+ -DSQLITE_ENABLE_HIDDEN_COLUMNS
+ --enable-json1
+ }
+
+ # The next group of configurations are used only by the
+ # Failure-Detection platform. They are all the same, but we need
+ # different names for them all so that they results appear in separate
+ # subdirectories.
+ #
+ Fail0 {-O0}
+ Fail2 {-O0}
+ Fail3 {-O0}
+ Fail4 {-O0}
+ FuzzFail1 {-O0}
+ FuzzFail2 {-O0}
+}]
+
+array set ::Platforms [strip_comments {
+ Linux-x86_64 {
+ "Check-Symbols" checksymbols
+ "Fast-One" "fuzztest test"
+ "Debug-One" "mptest test"
+ "Have-Not" test
+ "Secure-Delete" test
+ "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
+ "User-Auth" tcltest
+ "Update-Delete-Limit" test
+ "Extra-Robustness" test
+ "Device-Two" "threadtest test"
+ "No-lookaside" test
+ "Devkit" test
+ "Apple" test
+ "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test}
+ "Device-One" fulltest
+ "Default" "threadtest fulltest"
+ "Valgrind" valgrindtest
+ }
+ Linux-i686 {
+ "Devkit" test
+ "Have-Not" test
+ "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
+ "Device-One" test
+ "Device-Two" test
+ "Default" "threadtest fulltest"
+ }
+ Darwin-i386 {
+ "Locking-Style" "mptest test"
+ "Have-Not" test
+ "Apple" "threadtest fulltest"
+ }
+ Darwin-x86_64 {
+ "Locking-Style" "mptest test"
+ "Have-Not" test
+ "Apple" "threadtest fulltest"
+ }
+ "Windows NT-intel" {
+ "Stdcall" test
+ "Have-Not" test
+ "Default" "mptest fulltestonly"
+ }
+ "Windows NT-amd64" {
+ "Stdcall" test
+ "Have-Not" test
+ "Default" "mptest fulltestonly"
+ }
+
+ # The Failure-Detection platform runs various tests that deliberately
+ # fail. This is used as a test of this script to verify that this script
+ # correctly identifies failures.
+ #
+ Failure-Detection {
+ Fail0 "TEST_FAILURE=0 test"
+ Sanitize "TEST_FAILURE=1 test"
+ Fail2 "TEST_FAILURE=2 valgrindtest"
+ Fail3 "TEST_FAILURE=3 valgrindtest"
+ Fail4 "TEST_FAILURE=4 test"
+ FuzzFail1 "TEST_FAILURE=5 test"
+ FuzzFail2 "TEST_FAILURE=5 valgrindtest"
+ }
+}]
+
+
+# End of configuration section.
+#########################################################################
+#########################################################################
+
+# Configuration verification: Check that each entry in the list of configs
+# specified for each platforms exists.
+#
+foreach {key value} [array get ::Platforms] {
+ foreach {v t} $value {
+ if {0==[info exists ::Configs($v)]} {
+ puts stderr "No such configuration: \"$v\""
+ exit -1
+ }
+ }
+}
+
+# Output log. Disabled for slave interpreters.
+#
+if {[lindex $argv end]!="--slave"} {
+ set LOG [open releasetest-out.txt w]
+ proc PUTS {txt} {
+ puts $txt
+ puts $::LOG $txt
+ flush $::LOG
+ }
+ proc PUTSNNL {txt} {
+ puts -nonewline $txt
+ puts -nonewline $::LOG $txt
+ flush $::LOG
+ }
+ proc PUTSERR {txt} {
+ puts stderr $txt
+ puts $::LOG $txt
+ flush $::LOG
+ }
+ puts $LOG "$argv0 $argv"
+ set tm0 [clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S} -gmt 1]
+ puts $LOG "start-time: $tm0 UTC"
+} else {
+ proc PUTS {txt} {
+ puts $txt
+ }
+ proc PUTSNNL {txt} {
+ puts -nonewline $txt
+ }
+ proc PUTSERR {txt} {
+ puts stderr $txt
+ }
+}
+
+# Open the file $logfile and look for a report on the number of errors
+# and the number of test cases run. Add these values to the global
+# $::NERRCASE and $::NTESTCASE variables.
+#
+# If any errors occur, then write into $errmsgVar the text of an appropriate
+# one-line error message to show on the output.
+#
+proc count_tests_and_errors {logfile rcVar errmsgVar} {
+ if {$::DRYRUN} return
+ upvar 1 $rcVar rc $errmsgVar errmsg
+ 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 ::NERRCASE $nerr
+ incr ::NTESTCASE $ntest
+ set seen 1
+ if {$nerr>0} {
+ set rc 1
+ set errmsg $line
+ }
+ }
+ if {[regexp {runtime error: +(.*)} $line all msg]} {
+ # skip over "value is outside range" errors
+ if {[regexp {value .* is outside the range of representable} $line]} {
+ # noop
+ } elseif {[regexp {overflow: .* cannot be represented} $line]} {
+ # noop
+ } else {
+ incr ::NERRCASE
+ if {$rc==0} {
+ set rc 1
+ set errmsg $msg
+ }
+ }
+ }
+ if {[regexp {fatal error +(.*)} $line all msg]} {
+ incr ::NERRCASE
+ if {$rc==0} {
+ set rc 1
+ set errmsg $msg
+ }
+ }
+ if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
+ incr ::NERRCASE
+ if {$rc==0} {
+ set rc 1
+ set errmsg $all
+ }
+ }
+ if {[regexp {^VERSION: 3\.\d+.\d+} $line]} {
+ set v [string range $line 9 end]
+ if {$::SQLITE_VERSION eq ""} {
+ set ::SQLITE_VERSION $v
+ } elseif {$::SQLITE_VERSION ne $v} {
+ set rc 1
+ set errmsg "version conflict: {$::SQLITE_VERSION} vs. {$v}"
+ }
+ }
+ }
+ close $fd
+ if {$::BUILDONLY} {
+ incr ::NTESTCASE
+ if {$rc!=0} {
+ set errmsg "Build failed"
+ }
+ } elseif {!$seen} {
+ set rc 1
+ set errmsg "Test did not complete"
+ if {[file readable core]} {
+ append errmsg " - core file exists"
+ }
+ }
+}
+
+#--------------------------------------------------------------------------
+# This command is invoked as the [main] routine for scripts run with the
+# "--slave" option.
+#
+# For each test (i.e. "configure && make test" execution), the master
+# process spawns a process with the --slave option. It writes two lines
+# to the slaves stdin. The first contains a single boolean value - the
+# value of ::TRACE to use in the slave script. The second line contains a
+# list in the same format as each element of the list passed to the
+# [run_all_test_suites] command in the master process.
+#
+# The slave then runs the "configure && make test" commands specified. It
+# exits successfully if the tests passes, or with a non-zero error code
+# otherwise.
+#
+proc run_slave_test {} {
+ # Read global vars configuration from stdin.
+ set V [gets stdin]
+ foreach {::TRACE ::MSVC ::DRYRUN ::KEEPFILES} $V {}
+
+ # Read the test-suite configuration from stdin.
+ set T [gets stdin]
+ foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
+
+ # Create and switch to the test directory.
+ set normaldir [file normalize $dir]
+ set ::env(SQLITE_TMPDIR) $normaldir
+ trace_cmd file mkdir $dir
+ trace_cmd cd $dir
+ catch {file delete core}
+ catch {file delete test.log}
+
+ # Run the "./configure && make" commands.
+ set rc 0
+ set rc [catch [configureCommand $configOpts]]
+ if {!$rc} {
+ if {[info exists ::env(TCLSH_CMD)]} {
+ set savedEnv(TCLSH_CMD) $::env(TCLSH_CMD)
+ } else {
+ unset -nocomplain savedEnv(TCLSH_CMD)
+ }
+ set ::env(TCLSH_CMD) [file nativename [info nameofexecutable]]
+
+ # Create a file called "makecommand.sh" containing the text of
+ # the make command line.
+ catch {
+ set cmd [makeCommand $testtarget $makeOpts $cflags $opts]
+ set fd [open makecommand.sh w]
+ foreach e $cmd {
+ if {[string first " " $e]>=0} {
+ puts -nonewline $fd "\"$e\""
+ } else {
+ puts -nonewline $fd $e
+ }
+ puts -nonewline $fd " "
+ }
+ puts $fd ""
+ close $fd
+ } msg
+
+ # Run the make command.
+ set rc [catch {trace_cmd exec {*}$cmd >>& test.log} msg]
+ if {[info exists savedEnv(TCLSH_CMD)]} {
+ set ::env(TCLSH_CMD) $savedEnv(TCLSH_CMD)
+ } else {
+ unset -nocomplain ::env(TCLSH_CMD)
+ }
+ }
+
+ # Clean up lots of extra files if --keep was not specified.
+ if {$::KEEPFILES==0} { cleanup $normaldir }
+
+ # Exis successfully if the test passed, or with a non-zero error code
+ # otherwise.
+ exit $rc
+}
+
+# This command is invoked in the master process each time a slave
+# file-descriptor is readable.
+#
+proc slave_fileevent {fd T tm1} {
+ global G
+ foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
+
+ if {[eof $fd]} {
+ fconfigure $fd -blocking 1
+ set rc [catch { close $fd }]
+
+ set errmsg {}
+ set logfile [file join $dir test.log]
+ if {[file exists $logfile]} {
+ count_tests_and_errors [file join $dir test.log] rc errmsg
+ } elseif {$rc==0 && !$::DRYRUN} {
+ set rc 1
+ set errmsg "no test.log file..."
+ }
+
+ if {!$::TRACE} {
+ set tm2 [clock seconds]
+ set hours [expr {($tm2-$tm1)/3600}]
+ set minutes [expr {(($tm2-$tm1)/60)%60}]
+ set seconds [expr {($tm2-$tm1)%60}]
+ set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]
+
+ if {$rc} {
+ set status FAIL
+ incr ::NERR
+ } else {
+ set status Ok
+ }
+
+ set n [string length $title]
+ if {$::PROGRESS_MSGS} {
+ PUTS "finished: ${title}[string repeat . [expr {53-$n}]] $status $tm"
+ } else {
+ PUTS "${title}[string repeat . [expr {63-$n}]] $status $tm"
+ }
+ if {$errmsg!=""} {PUTS " $errmsg"}
+ flush stdout
+ }
+
+ incr G(nJob) -1
+ } else {
+ set line [gets $fd]
+ if {[string trim $line] != ""} {
+ puts "Trace : $title - \"$line\""
+ }
+ }
+}
+
+#--------------------------------------------------------------------------
+# The only argument passed to this function is a list of test-suites to
+# run. Each "test-suite" is itself a list consisting of the following
+# elements:
+#
+# * Test title (for display).
+# * The name of the directory to run the test in.
+# * The argument for [configureCommand]
+# * The first argument for [makeCommand]
+# * The second argument for [makeCommand]
+# * The third argument for [makeCommand]
+#
+proc run_all_test_suites {alltests} {
+ global G
+ set tests $alltests
+
+ set G(nJob) 0
+
+ while {[llength $tests]>0 || $G(nJob)>0} {
+ if {$G(nJob)>=$::JOBS || [llength $tests]==0} {
+ vwait G(nJob)
+ }
+
+ if {[llength $tests]>0} {
+ set T [lindex $tests 0]
+ set tests [lrange $tests 1 end]
+ foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
+ if {$::PROGRESS_MSGS && !$::TRACE} {
+ set n [string length $title]
+ PUTS "starting: ${title} at [now]"
+ flush stdout
+ }
+
+ # Run the job.
+ #
+ set tm1 [clock seconds]
+ incr G(nJob)
+ set script [file normalize [info script]]
+ set fd [open "|[info nameofexecutable] $script --slave" r+]
+ fconfigure $fd -blocking 0
+ fileevent $fd readable [list slave_fileevent $fd $T $tm1]
+ puts $fd [list $::TRACE $::MSVC $::DRYRUN $::KEEPFILES]
+ puts $fd [list {*}$T]
+ flush $fd
+ }
+ }
+}
+
+proc add_test_suite {listvar name testtarget config} {
+ upvar $listvar alltests
+
+ # Tcl variable $opts is used to build up the value used to set the
+ # OPTS Makefile variable. Variable $cflags holds the value for
+ # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
+ # CFLAGS is only passed to gcc.
+ #
+ set makeOpts ""
+ set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
+ set opts ""
+ set title ${name}($testtarget)
+ set configOpts $::WITHTCL
+ set skip 0
+
+ regsub -all {#[^\n]*\n} $config \n config
+ foreach arg $config {
+ if {$skip} {
+ set skip 0
+ continue
+ }
+ if {[regexp {^-[UD]} $arg]} {
+ lappend opts $arg
+ } elseif {[regexp {^[A-Z]+=} $arg]} {
+ lappend testtarget $arg
+ } elseif {[regexp {^if:([a-z]+)(.*)} $arg all key tail]} {
+ # Arguments of the form 'if:os=="Linux"' will cause the subsequent
+ # argument to be skipped if the $tcl_platform(os) is not "Linux", for
+ # example...
+ set skip [expr !(\$::tcl_platform($key)$tail)]
+ } elseif {[regexp {^--(enable|disable)-} $arg]} {
+ if {$::MSVC} {
+ if {$arg eq "--disable-amalgamation"} {
+ lappend makeOpts USE_AMALGAMATION=0
+ continue
+ }
+ if {$arg eq "--disable-shared"} {
+ lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0
+ continue
+ }
+ if {$arg eq "--enable-fts5"} {
+ lappend opts -DSQLITE_ENABLE_FTS5
+ continue
+ }
+ if {$arg eq "--enable-json1"} {
+ lappend opts -DSQLITE_ENABLE_JSON1
+ continue
+ }
+ if {$arg eq "--enable-shared"} {
+ lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
+ continue
+ }
+ }
+ lappend configOpts $arg
+ } else {
+ if {$::MSVC} {
+ if {$arg eq "-g"} {
+ lappend cflags -Zi
+ continue
+ }
+ if {[regexp -- {^-O(\d+)$} $arg all level]} then {
+ lappend makeOpts OPTIMIZATIONS=$level
+ continue
+ }
+ }
+ lappend cflags $arg
+ }
+ }
+
+ # Disable sync to make testing faster.
+ #
+ lappend opts -DSQLITE_NO_SYNC=1
+
+ # Some configurations already set HAVE_USLEEP; in that case, skip it.
+ #
+ if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} {
+ lappend opts -DHAVE_USLEEP=1
+ }
+
+ # Add the define for this platform.
+ #
+ if {$::tcl_platform(platform)=="windows"} {
+ lappend opts -DSQLITE_OS_WIN=1
+ } else {
+ lappend opts -DSQLITE_OS_UNIX=1
+ }
+
+ # Set the sub-directory to use.
+ #
+ set dir [string tolower [string map {- _ " " _} $name]]
+
+ # Join option lists into strings, using space as delimiter.
+ #
+ set makeOpts [join $makeOpts " "]
+ set cflags [join $cflags " "]
+ set opts [join $opts " "]
+
+ lappend alltests [list \
+ $title $dir $configOpts $testtarget $makeOpts $cflags $opts]
+}
+
+# The following procedure returns the "configure" command to be exectued for
+# the current platform, which may be Windows (via MinGW, etc).
+#
+proc configureCommand {opts} {
+ if {$::MSVC} return [list]; # This is not needed for MSVC.
+ set result [list trace_cmd exec]
+ if {$::tcl_platform(platform)=="windows"} {
+ lappend result sh
+ }
+ lappend result $::SRCDIR/configure --enable-load-extension
+ foreach x $opts {lappend result $x}
+ lappend result >& test.log
+}
+
+# The following procedure returns the "make" command to be executed for the
+# specified targets, compiler flags, and options.
+#
+proc makeCommand { targets makeOpts cflags opts } {
+ set result [list]
+ if {$::MSVC} {
+ set nmakeDir [file nativename $::SRCDIR]
+ set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]]
+ lappend result nmake /f $nmakeFile TOP=$nmakeDir
+ set tclDir [file nativename [file normalize \
+ [file dirname [file dirname [info nameofexecutable]]]]]
+ lappend result "TCLDIR=$tclDir"
+ if {[regexp {USE_STDCALL=1} $cflags]} {
+ lappend result USE_STDCALL=1
+ }
+ } else {
+ lappend result make
+ }
+ foreach makeOpt $makeOpts {
+ lappend result $makeOpt
+ }
+ lappend result clean
+ foreach target $targets {
+ lappend result $target
+ }
+ lappend result CFLAGS=$cflags OPTS=$opts
+}
+
+# The following procedure prints its arguments if ::TRACE is true.
+# And it executes the command of its arguments in the calling context
+# if ::DRYRUN is false.
+#
+proc trace_cmd {args} {
+ if {$::TRACE} {
+ PUTS $args
+ }
+ set res ""
+ if {!$::DRYRUN} {
+ set res [uplevel 1 $args]
+ }
+ return $res
+}
+
+
+# This proc processes the command line options passed to this script.
+# Currently the only option supported is "-makefile", default
+# "releasetest.mk". Set the ::MAKEFILE variable to the value of this
+# option.
+#
+proc process_options {argv} {
+ set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]]
+ set ::QUICK 0
+ set ::MSVC 0
+ set ::BUILDONLY 0
+ set ::DRYRUN 0
+ set ::TRACE 0
+ set ::JOBS 1
+ set ::PROGRESS_MSGS 0
+ set ::WITHTCL {}
+ set ::FORCE 0
+ set ::KEEPFILES 0 ;# Keep extra files after test run
+ set config {}
+ set platform $::tcl_platform(os)-$::tcl_platform(machine)
+
+ for {set i 0} {$i < [llength $argv]} {incr i} {
+ set x [lindex $argv $i]
+ if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]}
+ switch -glob -- $x {
+ -slave {
+ run_slave_test
+ exit
+ }
+
+ # Undocumented legacy option: --srcdir DIRECTORY
+ #
+ # DIRECTORY is the root of the SQLite checkout. This sets the
+ # SRCDIR global variable. But that variable is already set
+ # automatically so there really is no reason to have this option.
+ #
+ -srcdir {
+ incr i
+ set ::SRCDIR [file normalize [lindex $argv $i]]
+ }
+
+ -platform {
+ incr i
+ set platform [lindex $argv $i]
+ }
+
+ -jobs {
+ incr i
+ set ::JOBS [lindex $argv $i]
+ }
+
+ -progress {
+ set ::PROGRESS_MSGS 1
+ }
+
+ -quick {
+ set ::QUICK 1
+ }
+ -veryquick {
+ set ::QUICK 2
+ }
+
+ -config {
+ incr i
+ set config [lindex $argv $i]
+ }
+
+ -msvc {
+ set ::MSVC 1
+ }
+
+ -buildonly {
+ set ::BUILDONLY 1
+ }
+
+ -dryrun {
+ set ::DRYRUN 1
+ }
+
+ -force -
+ -f {
+ set ::FORCE 1
+ }
+
+ -trace {
+ set ::TRACE 1
+ }
+
+ -info {
+ PUTS "Command-line Options:"
+ PUTS " --srcdir $::SRCDIR"
+ PUTS " --platform [list $platform]"
+ PUTS " --config [list $config]"
+ if {$::QUICK} {
+ if {$::QUICK==1} {PUTS " --quick"}
+ if {$::QUICK==2} {PUTS " --veryquick"}
+ }
+ if {$::MSVC} {PUTS " --msvc"}
+ if {$::BUILDONLY} {PUTS " --buildonly"}
+ if {$::DRYRUN} {PUTS " --dryrun"}
+ if {$::TRACE} {PUTS " --trace"}
+ PUTS "\nAvailable --platform options:"
+ foreach y [lsort [array names ::Platforms]] {
+ PUTS " [list $y]"
+ }
+ PUTS "\nAvailable --config options:"
+ foreach y [lsort [array names ::Configs]] {
+ PUTS " [list $y]"
+ }
+ exit
+ }
+
+ -g {
+ lappend ::EXTRACONFIG [lindex $argv $i]
+ }
+
+ -keep {
+ set ::KEEPFILES 1
+ }
+
+ -with-tcl=* {
+ set ::WITHTCL -$x
+ }
+
+ -D* -
+ -O* -
+ -enable-* -
+ -disable-* -
+ *=* {
+ lappend ::EXTRACONFIG [lindex $argv $i]
+ }
+
+ default {
+ PUTSERR ""
+ PUTSERR [string trim $::USAGE_MESSAGE]
+ exit -1
+ }
+ }
+ }
+
+ if {0==[info exists ::Platforms($platform)]} {
+ PUTS "Unknown platform: $platform"
+ PUTSNNL "Set the -platform option to "
+ set print [list]
+ foreach p [array names ::Platforms] {
+ lappend print "\"$p\""
+ }
+ lset print end "or [lindex $print end]"
+ PUTS "[join $print {, }]."
+ exit
+ }
+
+ if {$config!=""} {
+ if {[llength $config]==1} {lappend config fulltest}
+ set ::CONFIGLIST $config
+ } else {
+ if {$::JOBS>1} {
+ set ::CONFIGLIST {}
+ foreach {target zConfig} [lreverse $::Platforms($platform)] {
+ append ::CONFIGLIST [format " %-25s %s\n" \
+ [list $zConfig] [list $target]]
+ }
+ } else {
+ set ::CONFIGLIST $::Platforms($platform)
+ }
+ }
+ PUTS "Running the following test configurations for $platform:"
+ PUTS " [string trim $::CONFIGLIST]"
+ PUTSNNL "Flags:"
+ if {$::PROGRESS_MSGS} {PUTSNNL " --progress"}
+ if {$::DRYRUN} {PUTSNNL " --dryrun"}
+ if {$::BUILDONLY} {PUTSNNL " --buildonly"}
+ if {$::MSVC} {PUTSNNL " --msvc"}
+ switch -- $::QUICK {
+ 1 {PUTSNNL " --quick"}
+ 2 {PUTSNNL " --veryquick"}
+ }
+ if {$::JOBS>1} {PUTSNNL " --jobs $::JOBS"}
+ PUTS ""
+}
+
+# Check to see if there are uncommitted changes in the SQLite source
+# checkout. Exit if there are. Except: Do nothing if the --force
+# flag is used. Also, ignore this test if the fossil binary is
+# unavailable, or if the source tree is not a valid fossil checkout.
+#
+proc check_uncommitted {} {
+ if {$::FORCE} return
+ set pwd [pwd]
+ cd $::SRCDIR
+ if {[catch {exec fossil changes} res]==0 && [string trim $res]!=""} {
+ puts "ERROR: The check-out contains uncommitted changes:"
+ puts $res
+ puts "Use the -f or --force options to override"
+ exit 1
+ }
+ cd $pwd
+}
+
+# A test run has just finished in directory $dir. This command deletes all
+# non-essential files from the directory. Specifically, everything except
+#
+# * The "testfixture" and "sqlite3" binaries,
+# * The "test-out.log" and "test.log" log files.
+#
+proc cleanup {dir} {
+ set K(testfixture) 1
+ set K(testfixture.exe) 1
+ set K(sqlite3) 1
+ set K(sqlite3.exe) 1
+ set K(test-out.txt) 1
+ set K(test.log) 1
+
+ foreach f [glob -nocomplain [file join $dir *]] {
+ set tail [file tail $f]
+ if {[info exists K($tail)]==0} {
+ file delete -force $f
+ }
+ }
+}
+
+
+# Main routine.
+#
+proc main {argv} {
+
+ # Process any command line options.
+ set ::EXTRACONFIG {}
+ process_options $argv
+ if {!$::DRYRUN} check_uncommitted
+ PUTS [string repeat * 79]
+
+ set ::NERR 0
+ set ::NTEST 0
+ set ::NTESTCASE 0
+ set ::NERRCASE 0
+ set ::SQLITE_VERSION {}
+ set STARTTIME [clock seconds]
+ foreach {zConfig target} $::CONFIGLIST {
+ if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target
+ || "valgrindtest" in $target)} {
+ PUTS "Skipping $zConfig / $target for MSVC..."
+ continue
+ }
+ if {$target ne "checksymbols"} {
+ switch -- $::QUICK {
+ 1 {set target quicktest}
+ 2 {set target smoketest}
+ }
+ if {$::BUILDONLY} {
+ set target testfixture
+ if {$::tcl_platform(platform)=="windows"} {
+ append target .exe
+ }
+ }
+ }
+ set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]
+
+ incr NTEST
+ add_test_suite all $zConfig $target $config_options
+
+ # If the configuration included the SQLITE_DEBUG option, then remove
+ # it and run veryquick.test. If it did not include the SQLITE_DEBUG option
+ # add it and run veryquick.test.
+ if {$target!="checksymbols" && $target!="valgrindtest"
+ && $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} {
+ set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
+ set xtarget $target
+ regsub -all {fulltest[a-z]*} $xtarget test xtarget
+ regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
+ if {$debug_idx < 0} {
+ incr NTEST
+ append config_options " -DSQLITE_DEBUG=1 -DSQLITE_EXTRA_IFNULLROW=1"
+ add_test_suite all "${zConfig}_debug" $xtarget $config_options
+ } else {
+ incr NTEST
+ regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options
+ regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options
+ add_test_suite all "${zConfig}_ndebug" $xtarget $config_options
+ }
+ }
+ }
+
+ run_all_test_suites $all
+
+ set elapsetime [expr {[clock seconds]-$STARTTIME}]
+ set hr [expr {$elapsetime/3600}]
+ set min [expr {($elapsetime/60)%60}]
+ set sec [expr {$elapsetime%60}]
+ set etime [format (%02d:%02d:%02d) $hr $min $sec]
+ if {$::JOBS>1} {append etime " $::JOBS cores"}
+ if {[catch {exec hostname} HNAME]==0} {append etime " on $HNAME"}
+ PUTS [string repeat * 79]
+ incr ::NERRCASE $::NERR
+ PUTS "$::NERRCASE failures out of $::NTESTCASE tests in $etime"
+ if {$::SQLITE_VERSION ne ""} {
+ PUTS "SQLite $::SQLITE_VERSION"
+ }
+}
+
+main $argv