Enhance the command-line completion extension to return the names of
[sqlite.git] / test / releasetest.tcl
blob599ebd791df7b1ffd64d5577b1e844766ad0e29b
1 #!/usr/bin/tclsh
3 # Documentation for this script. This may be output to stderr
4 # if the script is invoked incorrectly. See the [process_options]
5 # proc below.
7 set ::USAGE_MESSAGE {
8 This Tcl script is used to test the various configurations required
9 before releasing a new version. Supported command line options (all
10 optional) are:
12 --buildonly (Just build testfixture - do not run)
13 --config CONFIGNAME (Run only CONFIGNAME)
14 --dryrun (Print what would have happened)
15 -f|--force (Run even if uncommitted changes)
16 --info (Show diagnostic info)
17 --jobs N (Use N processes - default 1)
18 --keep (Delete no files after each test run)
19 --msvc (Use MSVC as the compiler)
20 --platform PLATFORM (see below)
21 --progress (Show progress messages)
22 --quick (Run "veryquick.test" only)
23 --veryquick (Run "make smoketest" only)
24 --with-tcl=DIR (Use TCL build at DIR)
26 The script determines the default value for --platform using the
27 $tcl_platform(os) and $tcl_platform(machine) variables. Supported
28 platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386",
29 "Darwin-x86_64", "Windows NT-intel", and "Windows NT-amd64".
31 Every test begins with a fresh run of the configure script at the top
32 of the SQLite source tree.
35 # Return a timestamp of the form HH:MM:SS
37 proc now {} {
38 return [clock format [clock seconds] -format %H:%M:%S]
41 # Omit comments (text between # and \n) in a long multi-line string.
43 proc strip_comments {in} {
44 regsub -all {#[^\n]*\n} $in {} out
45 return $out
48 array set ::Configs [strip_comments {
49 "Default" {
50 -O2
51 --disable-amalgamation --disable-shared
52 --enable-session
54 "Sanitize" {
55 CC=clang -fsanitize=undefined
56 -DSQLITE_ENABLE_STAT4
57 --enable-session
59 "Stdcall" {
60 -DUSE_STDCALL=1
61 -O2
63 "Have-Not" {
64 # The "Have-Not" configuration sets all possible -UHAVE_feature options
65 # in order to verify that the code works even on platforms that lack
66 # these support services.
67 -DHAVE_FDATASYNC=0
68 -DHAVE_GMTIME_R=0
69 -DHAVE_ISNAN=0
70 -DHAVE_LOCALTIME_R=0
71 -DHAVE_LOCALTIME_S=0
72 -DHAVE_MALLOC_USABLE_SIZE=0
73 -DHAVE_STRCHRNUL=0
74 -DHAVE_USLEEP=0
75 -DHAVE_UTIME=0
77 "Unlock-Notify" {
78 -O2
79 -DSQLITE_ENABLE_UNLOCK_NOTIFY
80 -DSQLITE_THREADSAFE
81 -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
83 "Secure-Delete" {
84 -O2
85 -DSQLITE_SECURE_DELETE=1
86 -DSQLITE_SOUNDEX=1
88 "Update-Delete-Limit" {
89 -O2
90 -DSQLITE_DEFAULT_FILE_FORMAT=4
91 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
92 -DSQLITE_ENABLE_STMT_SCANSTATUS
93 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS
94 -DSQLITE_ENABLE_CURSOR_HINTS
95 --enable-json1
97 "Check-Symbols" {
98 -DSQLITE_MEMDEBUG=1
99 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
100 -DSQLITE_ENABLE_FTS3=1
101 -DSQLITE_ENABLE_RTREE=1
102 -DSQLITE_ENABLE_MEMSYS5=1
103 -DSQLITE_ENABLE_MEMSYS3=1
104 -DSQLITE_ENABLE_COLUMN_METADATA=1
105 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
106 -DSQLITE_SECURE_DELETE=1
107 -DSQLITE_SOUNDEX=1
108 -DSQLITE_ENABLE_ATOMIC_WRITE=1
109 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
110 -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
111 -DSQLITE_ENABLE_STAT4
112 -DSQLITE_ENABLE_STMT_SCANSTATUS
113 --enable-json1 --enable-fts5 --enable-session
115 "Debug-One" {
116 --disable-shared
117 -O2 -funsigned-char
118 -DSQLITE_DEBUG=1
119 -DSQLITE_MEMDEBUG=1
120 -DSQLITE_MUTEX_NOOP=1
121 -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
122 -DSQLITE_ENABLE_FTS3=1
123 -DSQLITE_ENABLE_RTREE=1
124 -DSQLITE_ENABLE_MEMSYS5=1
125 -DSQLITE_ENABLE_COLUMN_METADATA=1
126 -DSQLITE_ENABLE_STAT4
127 -DSQLITE_ENABLE_HIDDEN_COLUMNS
128 -DSQLITE_MAX_ATTACHED=125
129 -DSQLITE_MUTATION_TEST
131 "Fast-One" {
133 -DSQLITE_ENABLE_FTS4=1
134 -DSQLITE_ENABLE_RTREE=1
135 -DSQLITE_ENABLE_STAT4
136 -DSQLITE_ENABLE_RBU
137 -DSQLITE_MAX_ATTACHED=125
138 -DLONGDOUBLE_TYPE=double
139 --enable-session
141 "Device-One" {
143 -DSQLITE_DEBUG=1
144 -DSQLITE_DEFAULT_AUTOVACUUM=1
145 -DSQLITE_DEFAULT_CACHE_SIZE=64
146 -DSQLITE_DEFAULT_PAGE_SIZE=1024
147 -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32
148 -DSQLITE_DISABLE_LFS=1
149 -DSQLITE_ENABLE_ATOMIC_WRITE=1
150 -DSQLITE_ENABLE_IOTRACE=1
151 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
152 -DSQLITE_MAX_PAGE_SIZE=4096
153 -DSQLITE_OMIT_LOAD_EXTENSION=1
154 -DSQLITE_OMIT_PROGRESS_CALLBACK=1
155 -DSQLITE_OMIT_VIRTUALTABLE=1
156 -DSQLITE_ENABLE_HIDDEN_COLUMNS
157 -DSQLITE_TEMP_STORE=3
158 --enable-json1
160 "Device-Two" {
161 -DSQLITE_4_BYTE_ALIGNED_MALLOC=1
162 -DSQLITE_DEFAULT_AUTOVACUUM=1
163 -DSQLITE_DEFAULT_CACHE_SIZE=1000
164 -DSQLITE_DEFAULT_LOCKING_MODE=0
165 -DSQLITE_DEFAULT_PAGE_SIZE=1024
166 -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=1000
167 -DSQLITE_DISABLE_LFS=1
168 -DSQLITE_ENABLE_FTS3=1
169 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
170 -DSQLITE_ENABLE_RTREE=1
171 -DSQLITE_MAX_COMPOUND_SELECT=50
172 -DSQLITE_MAX_PAGE_SIZE=32768
173 -DSQLITE_OMIT_TRACE=1
174 -DSQLITE_TEMP_STORE=3
175 -DSQLITE_THREADSAFE=2
176 --enable-json1 --enable-fts5 --enable-session
178 "Locking-Style" {
180 -DSQLITE_ENABLE_LOCKING_STYLE=1
182 "Apple" {
184 -DHAVE_GMTIME_R=1
185 -DHAVE_ISNAN=1
186 -DHAVE_LOCALTIME_R=1
187 -DHAVE_PREAD=1
188 -DHAVE_PWRITE=1
189 -DHAVE_USLEEP=1
190 -DHAVE_USLEEP=1
191 -DHAVE_UTIME=1
192 -DSQLITE_DEFAULT_CACHE_SIZE=1000
193 -DSQLITE_DEFAULT_CKPTFULLFSYNC=1
194 -DSQLITE_DEFAULT_MEMSTATUS=1
195 -DSQLITE_DEFAULT_PAGE_SIZE=1024
196 -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1
197 -DSQLITE_ENABLE_API_ARMOR=1
198 -DSQLITE_ENABLE_AUTO_PROFILE=1
199 -DSQLITE_ENABLE_FLOCKTIMEOUT=1
200 -DSQLITE_ENABLE_FTS3=1
201 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
202 -DSQLITE_ENABLE_FTS3_TOKENIZER=1
203 if:os=="Darwin" -DSQLITE_ENABLE_LOCKING_STYLE=1
204 -DSQLITE_ENABLE_PERSIST_WAL=1
205 -DSQLITE_ENABLE_PURGEABLE_PCACHE=1
206 -DSQLITE_ENABLE_RTREE=1
207 -DSQLITE_ENABLE_SNAPSHOT=1
208 # -DSQLITE_ENABLE_SQLLOG=1
209 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
210 -DSQLITE_MAX_LENGTH=2147483645
211 -DSQLITE_MAX_VARIABLE_NUMBER=500000
212 # -DSQLITE_MEMDEBUG=1
213 -DSQLITE_NO_SYNC=1
214 -DSQLITE_OMIT_AUTORESET=1
215 -DSQLITE_OMIT_LOAD_EXTENSION=1
216 -DSQLITE_PREFER_PROXY_LOCKING=1
217 -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
218 -DSQLITE_THREADSAFE=2
219 -DSQLITE_USE_URI=1
220 -DSQLITE_WRITE_WALFRAME_PREBUFFERED=1
221 -DUSE_GUARDED_FD=1
222 -DUSE_PREAD=1
223 --enable-json1 --enable-fts5
225 "Extra-Robustness" {
226 -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
227 -DSQLITE_MAX_ATTACHED=62
229 "Devkit" {
230 -DSQLITE_DEFAULT_FILE_FORMAT=4
231 -DSQLITE_MAX_ATTACHED=30
232 -DSQLITE_ENABLE_COLUMN_METADATA
233 -DSQLITE_ENABLE_FTS4
234 -DSQLITE_ENABLE_FTS5
235 -DSQLITE_ENABLE_FTS4_PARENTHESIS
236 -DSQLITE_DISABLE_FTS4_DEFERRED
237 -DSQLITE_ENABLE_RTREE
238 --enable-json1 --enable-fts5
240 "No-lookaside" {
241 -DSQLITE_TEST_REALLOC_STRESS=1
242 -DSQLITE_OMIT_LOOKASIDE=1
243 -DHAVE_USLEEP=1
245 "Valgrind" {
246 -DSQLITE_ENABLE_STAT4
247 -DSQLITE_ENABLE_FTS4
248 -DSQLITE_ENABLE_RTREE
249 -DSQLITE_ENABLE_HIDDEN_COLUMNS
250 --enable-json1
253 # The next group of configurations are used only by the
254 # Failure-Detection platform. They are all the same, but we need
255 # different names for them all so that they results appear in separate
256 # subdirectories.
258 Fail0 {-O0}
259 Fail2 {-O0}
260 Fail3 {-O0}
261 Fail4 {-O0}
262 FuzzFail1 {-O0}
263 FuzzFail2 {-O0}
266 array set ::Platforms [strip_comments {
267 Linux-x86_64 {
268 "Check-Symbols" checksymbols
269 "Fast-One" fuzztest
270 "Debug-One" "mptest test"
271 "Have-Not" test
272 "Secure-Delete" test
273 "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
274 "Update-Delete-Limit" test
275 "Extra-Robustness" test
276 "Device-Two" test
277 "No-lookaside" test
278 "Devkit" test
279 "Apple" test
280 "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test}
281 "Device-One" fulltest
282 "Default" "threadtest fulltest"
283 "Valgrind" valgrindtest
285 Linux-i686 {
286 "Devkit" test
287 "Have-Not" test
288 "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
289 "Device-One" test
290 "Device-Two" test
291 "Default" "threadtest fulltest"
293 Darwin-i386 {
294 "Locking-Style" "mptest test"
295 "Have-Not" test
296 "Apple" "threadtest fulltest"
298 Darwin-x86_64 {
299 "Locking-Style" "mptest test"
300 "Have-Not" test
301 "Apple" "threadtest fulltest"
303 "Windows NT-intel" {
304 "Stdcall" test
305 "Have-Not" test
306 "Default" "mptest fulltestonly"
308 "Windows NT-amd64" {
309 "Stdcall" test
310 "Have-Not" test
311 "Default" "mptest fulltestonly"
314 # The Failure-Detection platform runs various tests that deliberately
315 # fail. This is used as a test of this script to verify that this script
316 # correctly identifies failures.
318 Failure-Detection {
319 Fail0 "TEST_FAILURE=0 test"
320 Sanitize "TEST_FAILURE=1 test"
321 Fail2 "TEST_FAILURE=2 valgrindtest"
322 Fail3 "TEST_FAILURE=3 valgrindtest"
323 Fail4 "TEST_FAILURE=4 test"
324 FuzzFail1 "TEST_FAILURE=5 test"
325 FuzzFail2 "TEST_FAILURE=5 valgrindtest"
330 # End of configuration section.
331 #########################################################################
332 #########################################################################
334 # Configuration verification: Check that each entry in the list of configs
335 # specified for each platforms exists.
337 foreach {key value} [array get ::Platforms] {
338 foreach {v t} $value {
339 if {0==[info exists ::Configs($v)]} {
340 puts stderr "No such configuration: \"$v\""
341 exit -1
346 # Output log. Disabled for slave interpreters.
348 if {[lindex $argv end]!="--slave"} {
349 set LOG [open releasetest-out.txt w]
350 proc PUTS {txt} {
351 puts $txt
352 puts $::LOG $txt
353 flush $::LOG
355 proc PUTSNNL {txt} {
356 puts -nonewline $txt
357 puts -nonewline $::LOG $txt
358 flush $::LOG
360 proc PUTSERR {txt} {
361 puts stderr $txt
362 puts $::LOG $txt
363 flush $::LOG
365 puts $LOG "$argv0 $argv"
366 set tm0 [clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S} -gmt 1]
367 puts $LOG "start-time: $tm0 UTC"
368 } else {
369 proc PUTS {txt} {
370 puts $txt
372 proc PUTSNNL {txt} {
373 puts -nonewline $txt
375 proc PUTSERR {txt} {
376 puts stderr $txt
380 # Open the file $logfile and look for a report on the number of errors
381 # and the number of test cases run. Add these values to the global
382 # $::NERRCASE and $::NTESTCASE variables.
384 # If any errors occur, then write into $errmsgVar the text of an appropriate
385 # one-line error message to show on the output.
387 proc count_tests_and_errors {logfile rcVar errmsgVar} {
388 if {$::DRYRUN} return
389 upvar 1 $rcVar rc $errmsgVar errmsg
390 set fd [open $logfile rb]
391 set seen 0
392 while {![eof $fd]} {
393 set line [gets $fd]
394 if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} {
395 incr ::NERRCASE $nerr
396 incr ::NTESTCASE $ntest
397 set seen 1
398 if {$nerr>0} {
399 set rc 1
400 set errmsg $line
403 if {[regexp {runtime error: +(.*)} $line all msg]} {
404 # skip over "value is outside range" errors
405 if {[regexp {value .* is outside the range of representable} $line]} {
406 # noop
407 } else {
408 incr ::NERRCASE
409 if {$rc==0} {
410 set rc 1
411 set errmsg $msg
415 if {[regexp {fatal error +(.*)} $line all msg]} {
416 incr ::NERRCASE
417 if {$rc==0} {
418 set rc 1
419 set errmsg $msg
422 if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
423 incr ::NERRCASE
424 if {$rc==0} {
425 set rc 1
426 set errmsg $all
429 if {[regexp {^VERSION: 3\.\d+.\d+} $line]} {
430 set v [string range $line 9 end]
431 if {$::SQLITE_VERSION eq ""} {
432 set ::SQLITE_VERSION $v
433 } elseif {$::SQLITE_VERSION ne $v} {
434 set rc 1
435 set errmsg "version conflict: {$::SQLITE_VERSION} vs. {$v}"
439 close $fd
440 if {$::BUILDONLY} {
441 incr ::NTESTCASE
442 if {$rc!=0} {
443 set errmsg "Build failed"
445 } elseif {!$seen} {
446 set rc 1
447 set errmsg "Test did not complete"
448 if {[file readable core]} {
449 append errmsg " - core file exists"
454 #--------------------------------------------------------------------------
455 # This command is invoked as the [main] routine for scripts run with the
456 # "--slave" option.
458 # For each test (i.e. "configure && make test" execution), the master
459 # process spawns a process with the --slave option. It writes two lines
460 # to the slaves stdin. The first contains a single boolean value - the
461 # value of ::TRACE to use in the slave script. The second line contains a
462 # list in the same format as each element of the list passed to the
463 # [run_all_test_suites] command in the master process.
465 # The slave then runs the "configure && make test" commands specified. It
466 # exits successfully if the tests passes, or with a non-zero error code
467 # otherwise.
469 proc run_slave_test {} {
470 # Read global vars configuration from stdin.
471 set V [gets stdin]
472 foreach {::TRACE ::MSVC ::DRYRUN ::KEEPFILES} $V {}
474 # Read the test-suite configuration from stdin.
475 set T [gets stdin]
476 foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
478 # Create and switch to the test directory.
479 set normaldir [file normalize $dir]
480 set ::env(SQLITE_TMPDIR) $normaldir
481 trace_cmd file mkdir $dir
482 trace_cmd cd $dir
483 catch {file delete core}
484 catch {file delete test.log}
486 # Run the "./configure && make" commands.
487 set rc 0
488 set rc [catch [configureCommand $configOpts]]
489 if {!$rc} {
490 if {[info exists ::env(TCLSH_CMD)]} {
491 set savedEnv(TCLSH_CMD) $::env(TCLSH_CMD)
492 } else {
493 unset -nocomplain savedEnv(TCLSH_CMD)
495 set ::env(TCLSH_CMD) [file nativename [info nameofexecutable]]
496 set rc [catch [makeCommand $testtarget $makeOpts $cflags $opts]]
497 if {[info exists savedEnv(TCLSH_CMD)]} {
498 set ::env(TCLSH_CMD) $savedEnv(TCLSH_CMD)
499 } else {
500 unset -nocomplain ::env(TCLSH_CMD)
504 # Clean up lots of extra files if --keep was not specified.
505 if {$::KEEPFILES==0} { cleanup $normaldir }
507 # Exis successfully if the test passed, or with a non-zero error code
508 # otherwise.
509 exit $rc
512 # This command is invoked in the master process each time a slave
513 # file-descriptor is readable.
515 proc slave_fileevent {fd T tm1} {
516 global G
517 foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
519 if {[eof $fd]} {
520 fconfigure $fd -blocking 1
521 set rc [catch { close $fd }]
523 set errmsg {}
524 set logfile [file join $dir test.log]
525 if {[file exists $logfile]} {
526 count_tests_and_errors [file join $dir test.log] rc errmsg
527 } elseif {$rc==0 && !$::DRYRUN} {
528 set rc 1
529 set errmsg "no test.log file..."
532 if {!$::TRACE} {
533 set tm2 [clock seconds]
534 set hours [expr {($tm2-$tm1)/3600}]
535 set minutes [expr {(($tm2-$tm1)/60)%60}]
536 set seconds [expr {($tm2-$tm1)%60}]
537 set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]
539 if {$rc} {
540 set status FAIL
541 incr ::NERR
542 } else {
543 set status Ok
546 set n [string length $title]
547 if {$::PROGRESS_MSGS} {
548 PUTS "finished: ${title}[string repeat . [expr {53-$n}]] $status $tm"
549 } else {
550 PUTS "${title}[string repeat . [expr {63-$n}]] $status $tm"
552 if {$errmsg!=""} {PUTS " $errmsg"}
553 flush stdout
556 incr G(nJob) -1
557 } else {
558 set line [gets $fd]
559 if {[string trim $line] != ""} {
560 puts "Trace : $title - \"$line\""
565 #--------------------------------------------------------------------------
566 # The only argument passed to this function is a list of test-suites to
567 # run. Each "test-suite" is itself a list consisting of the following
568 # elements:
570 # * Test title (for display).
571 # * The name of the directory to run the test in.
572 # * The argument for [configureCommand]
573 # * The first argument for [makeCommand]
574 # * The second argument for [makeCommand]
575 # * The third argument for [makeCommand]
577 proc run_all_test_suites {alltests} {
578 global G
579 set tests $alltests
581 set G(nJob) 0
583 while {[llength $tests]>0 || $G(nJob)>0} {
584 if {$G(nJob)>=$::JOBS || [llength $tests]==0} {
585 vwait G(nJob)
588 if {[llength $tests]>0} {
589 set T [lindex $tests 0]
590 set tests [lrange $tests 1 end]
591 foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
592 if {$::PROGRESS_MSGS && !$::TRACE} {
593 set n [string length $title]
594 PUTS "starting: ${title} at [now]"
595 flush stdout
598 # Run the job.
600 set tm1 [clock seconds]
601 incr G(nJob)
602 set script [file normalize [info script]]
603 set fd [open "|[info nameofexecutable] $script --slave" r+]
604 fconfigure $fd -blocking 0
605 fileevent $fd readable [list slave_fileevent $fd $T $tm1]
606 puts $fd [list $::TRACE $::MSVC $::DRYRUN $::KEEPFILES]
607 puts $fd [list {*}$T]
608 flush $fd
613 proc add_test_suite {listvar name testtarget config} {
614 upvar $listvar alltests
616 # Tcl variable $opts is used to build up the value used to set the
617 # OPTS Makefile variable. Variable $cflags holds the value for
618 # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
619 # CFLAGS is only passed to gcc.
621 set makeOpts ""
622 set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
623 set opts ""
624 set title ${name}($testtarget)
625 set configOpts $::WITHTCL
626 set skip 0
628 regsub -all {#[^\n]*\n} $config \n config
629 foreach arg $config {
630 if {$skip} {
631 set skip 0
632 continue
634 if {[regexp {^-[UD]} $arg]} {
635 lappend opts $arg
636 } elseif {[regexp {^[A-Z]+=} $arg]} {
637 lappend testtarget $arg
638 } elseif {[regexp {^if:([a-z]+)(.*)} $arg all key tail]} {
639 # Arguments of the form 'if:os=="Linux"' will cause the subsequent
640 # argument to be skipped if the $tcl_platform(os) is not "Linux", for
641 # example...
642 set skip [expr !(\$::tcl_platform($key)$tail)]
643 } elseif {[regexp {^--(enable|disable)-} $arg]} {
644 if {$::MSVC} {
645 if {$arg eq "--disable-amalgamation"} {
646 lappend makeOpts USE_AMALGAMATION=0
647 continue
649 if {$arg eq "--disable-shared"} {
650 lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0
651 continue
653 if {$arg eq "--enable-fts5"} {
654 lappend opts -DSQLITE_ENABLE_FTS5
655 continue
657 if {$arg eq "--enable-json1"} {
658 lappend opts -DSQLITE_ENABLE_JSON1
659 continue
661 if {$arg eq "--enable-shared"} {
662 lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
663 continue
666 lappend configOpts $arg
667 } else {
668 if {$::MSVC} {
669 if {$arg eq "-g"} {
670 lappend cflags -Zi
671 continue
673 if {[regexp -- {^-O(\d+)$} $arg all level]} then {
674 lappend makeOpts OPTIMIZATIONS=$level
675 continue
678 lappend cflags $arg
682 # Disable sync to make testing faster.
684 lappend opts -DSQLITE_NO_SYNC=1
686 # Some configurations already set HAVE_USLEEP; in that case, skip it.
688 if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} {
689 lappend opts -DHAVE_USLEEP=1
692 # Add the define for this platform.
694 if {$::tcl_platform(platform)=="windows"} {
695 lappend opts -DSQLITE_OS_WIN=1
696 } else {
697 lappend opts -DSQLITE_OS_UNIX=1
700 # Set the sub-directory to use.
702 set dir [string tolower [string map {- _ " " _} $name]]
704 # Join option lists into strings, using space as delimiter.
706 set makeOpts [join $makeOpts " "]
707 set cflags [join $cflags " "]
708 set opts [join $opts " "]
710 lappend alltests [list \
711 $title $dir $configOpts $testtarget $makeOpts $cflags $opts]
714 # The following procedure returns the "configure" command to be exectued for
715 # the current platform, which may be Windows (via MinGW, etc).
717 proc configureCommand {opts} {
718 if {$::MSVC} return [list]; # This is not needed for MSVC.
719 set result [list trace_cmd exec]
720 if {$::tcl_platform(platform)=="windows"} {
721 lappend result sh
723 lappend result $::SRCDIR/configure --enable-load-extension
724 foreach x $opts {lappend result $x}
725 lappend result >& test.log
728 # The following procedure returns the "make" command to be executed for the
729 # specified targets, compiler flags, and options.
731 proc makeCommand { targets makeOpts cflags opts } {
732 set result [list trace_cmd exec]
733 if {$::MSVC} {
734 set nmakeDir [file nativename $::SRCDIR]
735 set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]]
736 lappend result nmake /f $nmakeFile TOP=$nmakeDir
737 set tclDir [file nativename [file normalize \
738 [file dirname [file dirname [info nameofexecutable]]]]]
739 lappend result "TCLDIR=$tclDir"
740 if {[regexp {USE_STDCALL=1} $cflags]} {
741 lappend result USE_STDCALL=1
743 } else {
744 lappend result make
746 foreach makeOpt $makeOpts {
747 lappend result $makeOpt
749 lappend result clean
750 foreach target $targets {
751 lappend result $target
753 lappend result CFLAGS=$cflags OPTS=$opts >>& test.log
756 # The following procedure prints its arguments if ::TRACE is true.
757 # And it executes the command of its arguments in the calling context
758 # if ::DRYRUN is false.
760 proc trace_cmd {args} {
761 if {$::TRACE} {
762 PUTS $args
764 set res ""
765 if {!$::DRYRUN} {
766 set res [uplevel 1 $args]
768 return $res
772 # This proc processes the command line options passed to this script.
773 # Currently the only option supported is "-makefile", default
774 # "releasetest.mk". Set the ::MAKEFILE variable to the value of this
775 # option.
777 proc process_options {argv} {
778 set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]]
779 set ::QUICK 0
780 set ::MSVC 0
781 set ::BUILDONLY 0
782 set ::DRYRUN 0
783 set ::TRACE 0
784 set ::JOBS 1
785 set ::PROGRESS_MSGS 0
786 set ::WITHTCL {}
787 set ::FORCE 0
788 set ::KEEPFILES 0 ;# Keep extra files after test run
789 set config {}
790 set platform $::tcl_platform(os)-$::tcl_platform(machine)
792 for {set i 0} {$i < [llength $argv]} {incr i} {
793 set x [lindex $argv $i]
794 if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]}
795 switch -glob -- $x {
796 -slave {
797 run_slave_test
798 exit
801 # Undocumented legacy option: --srcdir DIRECTORY
803 # DIRECTORY is the root of the SQLite checkout. This sets the
804 # SRCDIR global variable. But that variable is already set
805 # automatically so there really is no reason to have this option.
807 -srcdir {
808 incr i
809 set ::SRCDIR [file normalize [lindex $argv $i]]
812 -platform {
813 incr i
814 set platform [lindex $argv $i]
817 -jobs {
818 incr i
819 set ::JOBS [lindex $argv $i]
822 -progress {
823 set ::PROGRESS_MSGS 1
826 -quick {
827 set ::QUICK 1
829 -veryquick {
830 set ::QUICK 2
833 -config {
834 incr i
835 set config [lindex $argv $i]
838 -msvc {
839 set ::MSVC 1
842 -buildonly {
843 set ::BUILDONLY 1
846 -dryrun {
847 set ::DRYRUN 1
850 -force -
851 -f {
852 set ::FORCE 1
855 -trace {
856 set ::TRACE 1
859 -info {
860 PUTS "Command-line Options:"
861 PUTS " --srcdir $::SRCDIR"
862 PUTS " --platform [list $platform]"
863 PUTS " --config [list $config]"
864 if {$::QUICK} {
865 if {$::QUICK==1} {PUTS " --quick"}
866 if {$::QUICK==2} {PUTS " --veryquick"}
868 if {$::MSVC} {PUTS " --msvc"}
869 if {$::BUILDONLY} {PUTS " --buildonly"}
870 if {$::DRYRUN} {PUTS " --dryrun"}
871 if {$::TRACE} {PUTS " --trace"}
872 PUTS "\nAvailable --platform options:"
873 foreach y [lsort [array names ::Platforms]] {
874 PUTS " [list $y]"
876 PUTS "\nAvailable --config options:"
877 foreach y [lsort [array names ::Configs]] {
878 PUTS " [list $y]"
880 exit
883 -g {
884 lappend ::EXTRACONFIG [lindex $argv $i]
887 -keep {
888 set ::KEEPFILES 1
891 -with-tcl=* {
892 set ::WITHTCL -$x
895 -D* -
896 -O* -
897 -enable-* -
898 -disable-* -
899 *=* {
900 lappend ::EXTRACONFIG [lindex $argv $i]
903 default {
904 PUTSERR ""
905 PUTSERR [string trim $::USAGE_MESSAGE]
906 exit -1
911 if {0==[info exists ::Platforms($platform)]} {
912 PUTS "Unknown platform: $platform"
913 PUTSNNL "Set the -platform option to "
914 set print [list]
915 foreach p [array names ::Platforms] {
916 lappend print "\"$p\""
918 lset print end "or [lindex $print end]"
919 PUTS "[join $print {, }]."
920 exit
923 if {$config!=""} {
924 if {[llength $config]==1} {lappend config fulltest}
925 set ::CONFIGLIST $config
926 } else {
927 if {$::JOBS>1} {
928 set ::CONFIGLIST {}
929 foreach {target zConfig} [lreverse $::Platforms($platform)] {
930 append ::CONFIGLIST [format " %-25s %s\n" \
931 [list $zConfig] [list $target]]
933 } else {
934 set ::CONFIGLIST $::Platforms($platform)
937 PUTS "Running the following test configurations for $platform:"
938 PUTS " [string trim $::CONFIGLIST]"
939 PUTSNNL "Flags:"
940 if {$::PROGRESS_MSGS} {PUTSNNL " --progress"}
941 if {$::DRYRUN} {PUTSNNL " --dryrun"}
942 if {$::BUILDONLY} {PUTSNNL " --buildonly"}
943 if {$::MSVC} {PUTSNNL " --msvc"}
944 switch -- $::QUICK {
945 1 {PUTSNNL " --quick"}
946 2 {PUTSNNL " --veryquick"}
948 if {$::JOBS>1} {PUTSNNL " --jobs $::JOBS"}
949 PUTS ""
952 # Check to see if there are uncommitted changes in the SQLite source
953 # checkout. Exit if there are. Except: Do nothing if the --force
954 # flag is used. Also, ignore this test if the fossil binary is
955 # unavailable, or if the source tree is not a valid fossil checkout.
957 proc check_uncommitted {} {
958 if {$::FORCE} return
959 set pwd [pwd]
960 cd $::SRCDIR
961 if {[catch {exec fossil changes} res]==0 && [string trim $res]!=""} {
962 puts "ERROR: The check-out contains uncommitted changes:"
963 puts $res
964 puts "Use the -f or --force options to override"
965 exit 1
967 cd $pwd
970 # A test run has just finished in directory $dir. This command deletes all
971 # non-essential files from the directory. Specifically, everything except
973 # * The "testfixture" and "sqlite3" binaries,
974 # * The "test-out.log" and "test.log" log files.
976 proc cleanup {dir} {
977 set K(testfixture) 1
978 set K(testfixture.exe) 1
979 set K(sqlite3) 1
980 set K(sqlite3.exe) 1
981 set K(test-out.txt) 1
982 set K(test.log) 1
984 foreach f [glob -nocomplain [file join $dir *]] {
985 set tail [file tail $f]
986 if {[info exists K($tail)]==0} {
987 file delete -force $f
993 # Main routine.
995 proc main {argv} {
997 # Process any command line options.
998 set ::EXTRACONFIG {}
999 process_options $argv
1000 if {!$::DRYRUN} check_uncommitted
1001 PUTS [string repeat * 79]
1003 set ::NERR 0
1004 set ::NTEST 0
1005 set ::NTESTCASE 0
1006 set ::NERRCASE 0
1007 set ::SQLITE_VERSION {}
1008 set STARTTIME [clock seconds]
1009 foreach {zConfig target} $::CONFIGLIST {
1010 if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target
1011 || "valgrindtest" in $target)} {
1012 PUTS "Skipping $zConfig / $target for MSVC..."
1013 continue
1015 if {$target ne "checksymbols"} {
1016 switch -- $::QUICK {
1017 1 {set target quicktest}
1018 2 {set target smoketest}
1020 if {$::BUILDONLY} {
1021 set target testfixture
1022 if {$::tcl_platform(platform)=="windows"} {
1023 append target .exe
1027 set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]
1029 incr NTEST
1030 add_test_suite all $zConfig $target $config_options
1032 # If the configuration included the SQLITE_DEBUG option, then remove
1033 # it and run veryquick.test. If it did not include the SQLITE_DEBUG option
1034 # add it and run veryquick.test.
1035 if {$target!="checksymbols" && $target!="valgrindtest"
1036 && $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} {
1037 set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
1038 set xtarget $target
1039 regsub -all {fulltest[a-z]*} $xtarget test xtarget
1040 regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
1041 if {$debug_idx < 0} {
1042 incr NTEST
1043 append config_options " -DSQLITE_DEBUG=1 -DSQLITE_EXTRA_IFNULLROW=1"
1044 add_test_suite all "${zConfig}_debug" $xtarget $config_options
1045 } else {
1046 incr NTEST
1047 regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options
1048 regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options
1049 add_test_suite all "${zConfig}_ndebug" $xtarget $config_options
1054 run_all_test_suites $all
1056 set elapsetime [expr {[clock seconds]-$STARTTIME}]
1057 set hr [expr {$elapsetime/3600}]
1058 set min [expr {($elapsetime/60)%60}]
1059 set sec [expr {$elapsetime%60}]
1060 set etime [format (%02d:%02d:%02d) $hr $min $sec]
1061 if {$::JOBS>1} {append etime " $::JOBS cores"}
1062 if {[catch {exec hostname} HNAME]==0} {append etime " on $HNAME"}
1063 PUTS [string repeat * 79]
1064 incr ::NERRCASE $::NERR
1065 PUTS "$::NERRCASE failures out of $::NTESTCASE tests in $etime"
1066 if {$::SQLITE_VERSION ne ""} {
1067 PUTS "SQLite $::SQLITE_VERSION"
1071 main $argv