modernc.org/cc@v1.0.1/v2/testdata/_sqlite/test/releasetest.tcl (about) 1 #!/usr/bin/tclsh 2 # 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. 6 # 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: 11 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) 25 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". 30 31 Every test begins with a fresh run of the configure script at the top 32 of the SQLite source tree. 33 } 34 35 # Return a timestamp of the form HH:MM:SS 36 # 37 proc now {} { 38 return [clock format [clock seconds] -format %H:%M:%S] 39 } 40 41 # Omit comments (text between # and \n) in a long multi-line string. 42 # 43 proc strip_comments {in} { 44 regsub -all {#[^\n]*\n} $in {} out 45 return $out 46 } 47 48 array set ::Configs [strip_comments { 49 "Default" { 50 -O2 51 --disable-amalgamation --disable-shared 52 --enable-session 53 } 54 "Sanitize" { 55 CC=clang -fsanitize=undefined 56 -DSQLITE_ENABLE_STAT4 57 --enable-session 58 } 59 "Stdcall" { 60 -DUSE_STDCALL=1 61 -O2 62 } 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 76 } 77 "Unlock-Notify" { 78 -O2 79 -DSQLITE_ENABLE_UNLOCK_NOTIFY 80 -DSQLITE_THREADSAFE 81 -DSQLITE_TCL_DEFAULT_FULLMUTEX=1 82 } 83 "Secure-Delete" { 84 -O2 85 -DSQLITE_SECURE_DELETE=1 86 -DSQLITE_SOUNDEX=1 87 } 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 96 } 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 114 } 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 130 } 131 "Fast-One" { 132 -O6 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 140 } 141 "Device-One" { 142 -O2 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 159 } 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 177 } 178 "Locking-Style" { 179 -O2 180 -DSQLITE_ENABLE_LOCKING_STYLE=1 181 } 182 "Apple" { 183 -Os 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 224 } 225 "Extra-Robustness" { 226 -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1 227 -DSQLITE_MAX_ATTACHED=62 228 } 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 239 } 240 "No-lookaside" { 241 -DSQLITE_TEST_REALLOC_STRESS=1 242 -DSQLITE_OMIT_LOOKASIDE=1 243 -DHAVE_USLEEP=1 244 } 245 "Valgrind" { 246 -DSQLITE_ENABLE_STAT4 247 -DSQLITE_ENABLE_FTS4 248 -DSQLITE_ENABLE_RTREE 249 -DSQLITE_ENABLE_HIDDEN_COLUMNS 250 --enable-json1 251 } 252 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. 257 # 258 Fail0 {-O0} 259 Fail2 {-O0} 260 Fail3 {-O0} 261 Fail4 {-O0} 262 FuzzFail1 {-O0} 263 FuzzFail2 {-O0} 264 }] 265 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 284 } 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" 292 } 293 Darwin-i386 { 294 "Locking-Style" "mptest test" 295 "Have-Not" test 296 "Apple" "threadtest fulltest" 297 } 298 Darwin-x86_64 { 299 "Locking-Style" "mptest test" 300 "Have-Not" test 301 "Apple" "threadtest fulltest" 302 } 303 "Windows NT-intel" { 304 "Stdcall" test 305 "Have-Not" test 306 "Default" "mptest fulltestonly" 307 } 308 "Windows NT-amd64" { 309 "Stdcall" test 310 "Have-Not" test 311 "Default" "mptest fulltestonly" 312 } 313 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. 317 # 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" 326 } 327 }] 328 329 330 # End of configuration section. 331 ######################################################################### 332 ######################################################################### 333 334 # Configuration verification: Check that each entry in the list of configs 335 # specified for each platforms exists. 336 # 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 342 } 343 } 344 } 345 346 # Output log. Disabled for slave interpreters. 347 # 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 354 } 355 proc PUTSNNL {txt} { 356 puts -nonewline $txt 357 puts -nonewline $::LOG $txt 358 flush $::LOG 359 } 360 proc PUTSERR {txt} { 361 puts stderr $txt 362 puts $::LOG $txt 363 flush $::LOG 364 } 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 371 } 372 proc PUTSNNL {txt} { 373 puts -nonewline $txt 374 } 375 proc PUTSERR {txt} { 376 puts stderr $txt 377 } 378 } 379 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. 383 # 384 # If any errors occur, then write into $errmsgVar the text of an appropriate 385 # one-line error message to show on the output. 386 # 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 401 } 402 } 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 412 } 413 } 414 } 415 if {[regexp {fatal error +(.*)} $line all msg]} { 416 incr ::NERRCASE 417 if {$rc==0} { 418 set rc 1 419 set errmsg $msg 420 } 421 } 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 427 } 428 } 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}" 436 } 437 } 438 } 439 close $fd 440 if {$::BUILDONLY} { 441 incr ::NTESTCASE 442 if {$rc!=0} { 443 set errmsg "Build failed" 444 } 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" 450 } 451 } 452 } 453 454 #-------------------------------------------------------------------------- 455 # This command is invoked as the [main] routine for scripts run with the 456 # "--slave" option. 457 # 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. 464 # 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. 468 # 469 proc run_slave_test {} { 470 # Read global vars configuration from stdin. 471 set V [gets stdin] 472 foreach {::TRACE ::MSVC ::DRYRUN ::KEEPFILES} $V {} 473 474 # Read the test-suite configuration from stdin. 475 set T [gets stdin] 476 foreach {title dir configOpts testtarget makeOpts cflags opts} $T {} 477 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} 485 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) 494 } 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) 501 } 502 } 503 504 # Clean up lots of extra files if --keep was not specified. 505 if {$::KEEPFILES==0} { cleanup $normaldir } 506 507 # Exis successfully if the test passed, or with a non-zero error code 508 # otherwise. 509 exit $rc 510 } 511 512 # This command is invoked in the master process each time a slave 513 # file-descriptor is readable. 514 # 515 proc slave_fileevent {fd T tm1} { 516 global G 517 foreach {title dir configOpts testtarget makeOpts cflags opts} $T {} 518 519 if {[eof $fd]} { 520 fconfigure $fd -blocking 1 521 set rc [catch { close $fd }] 522 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..." 530 } 531 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] 538 539 if {$rc} { 540 set status FAIL 541 incr ::NERR 542 } else { 543 set status Ok 544 } 545 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" 551 } 552 if {$errmsg!=""} {PUTS " $errmsg"} 553 flush stdout 554 } 555 556 incr G(nJob) -1 557 } else { 558 set line [gets $fd] 559 if {[string trim $line] != ""} { 560 puts "Trace : $title - \"$line\"" 561 } 562 } 563 } 564 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: 569 # 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] 576 # 577 proc run_all_test_suites {alltests} { 578 global G 579 set tests $alltests 580 581 set G(nJob) 0 582 583 while {[llength $tests]>0 || $G(nJob)>0} { 584 if {$G(nJob)>=$::JOBS || [llength $tests]==0} { 585 vwait G(nJob) 586 } 587 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 596 } 597 598 # Run the job. 599 # 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 609 } 610 } 611 } 612 613 proc add_test_suite {listvar name testtarget config} { 614 upvar $listvar alltests 615 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. 620 # 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 627 628 regsub -all {#[^\n]*\n} $config \n config 629 foreach arg $config { 630 if {$skip} { 631 set skip 0 632 continue 633 } 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 648 } 649 if {$arg eq "--disable-shared"} { 650 lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0 651 continue 652 } 653 if {$arg eq "--enable-fts5"} { 654 lappend opts -DSQLITE_ENABLE_FTS5 655 continue 656 } 657 if {$arg eq "--enable-json1"} { 658 lappend opts -DSQLITE_ENABLE_JSON1 659 continue 660 } 661 if {$arg eq "--enable-shared"} { 662 lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1 663 continue 664 } 665 } 666 lappend configOpts $arg 667 } else { 668 if {$::MSVC} { 669 if {$arg eq "-g"} { 670 lappend cflags -Zi 671 continue 672 } 673 if {[regexp -- {^-O(\d+)$} $arg all level]} then { 674 lappend makeOpts OPTIMIZATIONS=$level 675 continue 676 } 677 } 678 lappend cflags $arg 679 } 680 } 681 682 # Disable sync to make testing faster. 683 # 684 lappend opts -DSQLITE_NO_SYNC=1 685 686 # Some configurations already set HAVE_USLEEP; in that case, skip it. 687 # 688 if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} { 689 lappend opts -DHAVE_USLEEP=1 690 } 691 692 # Add the define for this platform. 693 # 694 if {$::tcl_platform(platform)=="windows"} { 695 lappend opts -DSQLITE_OS_WIN=1 696 } else { 697 lappend opts -DSQLITE_OS_UNIX=1 698 } 699 700 # Set the sub-directory to use. 701 # 702 set dir [string tolower [string map {- _ " " _} $name]] 703 704 # Join option lists into strings, using space as delimiter. 705 # 706 set makeOpts [join $makeOpts " "] 707 set cflags [join $cflags " "] 708 set opts [join $opts " "] 709 710 lappend alltests [list \ 711 $title $dir $configOpts $testtarget $makeOpts $cflags $opts] 712 } 713 714 # The following procedure returns the "configure" command to be exectued for 715 # the current platform, which may be Windows (via MinGW, etc). 716 # 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 722 } 723 lappend result $::SRCDIR/configure --enable-load-extension 724 foreach x $opts {lappend result $x} 725 lappend result >& test.log 726 } 727 728 # The following procedure returns the "make" command to be executed for the 729 # specified targets, compiler flags, and options. 730 # 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 if {[regexp {USE_STDCALL=1} $cflags]} { 738 lappend result USE_STDCALL=1 739 } 740 } else { 741 lappend result make 742 } 743 foreach makeOpt $makeOpts { 744 lappend result $makeOpt 745 } 746 lappend result clean 747 foreach target $targets { 748 lappend result $target 749 } 750 lappend result CFLAGS=$cflags OPTS=$opts >>& test.log 751 } 752 753 # The following procedure prints its arguments if ::TRACE is true. 754 # And it executes the command of its arguments in the calling context 755 # if ::DRYRUN is false. 756 # 757 proc trace_cmd {args} { 758 if {$::TRACE} { 759 PUTS $args 760 } 761 set res "" 762 if {!$::DRYRUN} { 763 set res [uplevel 1 $args] 764 } 765 return $res 766 } 767 768 769 # This proc processes the command line options passed to this script. 770 # Currently the only option supported is "-makefile", default 771 # "releasetest.mk". Set the ::MAKEFILE variable to the value of this 772 # option. 773 # 774 proc process_options {argv} { 775 set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]] 776 set ::QUICK 0 777 set ::MSVC 0 778 set ::BUILDONLY 0 779 set ::DRYRUN 0 780 set ::TRACE 0 781 set ::JOBS 1 782 set ::PROGRESS_MSGS 0 783 set ::WITHTCL {} 784 set ::FORCE 0 785 set ::KEEPFILES 0 ;# Keep extra files after test run 786 set config {} 787 set platform $::tcl_platform(os)-$::tcl_platform(machine) 788 789 for {set i 0} {$i < [llength $argv]} {incr i} { 790 set x [lindex $argv $i] 791 if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]} 792 switch -glob -- $x { 793 -slave { 794 run_slave_test 795 exit 796 } 797 798 # Undocumented legacy option: --srcdir DIRECTORY 799 # 800 # DIRECTORY is the root of the SQLite checkout. This sets the 801 # SRCDIR global variable. But that variable is already set 802 # automatically so there really is no reason to have this option. 803 # 804 -srcdir { 805 incr i 806 set ::SRCDIR [file normalize [lindex $argv $i]] 807 } 808 809 -platform { 810 incr i 811 set platform [lindex $argv $i] 812 } 813 814 -jobs { 815 incr i 816 set ::JOBS [lindex $argv $i] 817 } 818 819 -progress { 820 set ::PROGRESS_MSGS 1 821 } 822 823 -quick { 824 set ::QUICK 1 825 } 826 -veryquick { 827 set ::QUICK 2 828 } 829 830 -config { 831 incr i 832 set config [lindex $argv $i] 833 } 834 835 -msvc { 836 set ::MSVC 1 837 } 838 839 -buildonly { 840 set ::BUILDONLY 1 841 } 842 843 -dryrun { 844 set ::DRYRUN 1 845 } 846 847 -force - 848 -f { 849 set ::FORCE 1 850 } 851 852 -trace { 853 set ::TRACE 1 854 } 855 856 -info { 857 PUTS "Command-line Options:" 858 PUTS " --srcdir $::SRCDIR" 859 PUTS " --platform [list $platform]" 860 PUTS " --config [list $config]" 861 if {$::QUICK} { 862 if {$::QUICK==1} {PUTS " --quick"} 863 if {$::QUICK==2} {PUTS " --veryquick"} 864 } 865 if {$::MSVC} {PUTS " --msvc"} 866 if {$::BUILDONLY} {PUTS " --buildonly"} 867 if {$::DRYRUN} {PUTS " --dryrun"} 868 if {$::TRACE} {PUTS " --trace"} 869 PUTS "\nAvailable --platform options:" 870 foreach y [lsort [array names ::Platforms]] { 871 PUTS " [list $y]" 872 } 873 PUTS "\nAvailable --config options:" 874 foreach y [lsort [array names ::Configs]] { 875 PUTS " [list $y]" 876 } 877 exit 878 } 879 880 -g { 881 lappend ::EXTRACONFIG [lindex $argv $i] 882 } 883 884 -keep { 885 set ::KEEPFILES 1 886 } 887 888 -with-tcl=* { 889 set ::WITHTCL -$x 890 } 891 892 -D* - 893 -O* - 894 -enable-* - 895 -disable-* - 896 *=* { 897 lappend ::EXTRACONFIG [lindex $argv $i] 898 } 899 900 default { 901 PUTSERR "" 902 PUTSERR [string trim $::USAGE_MESSAGE] 903 exit -1 904 } 905 } 906 } 907 908 if {0==[info exists ::Platforms($platform)]} { 909 PUTS "Unknown platform: $platform" 910 PUTSNNL "Set the -platform option to " 911 set print [list] 912 foreach p [array names ::Platforms] { 913 lappend print "\"$p\"" 914 } 915 lset print end "or [lindex $print end]" 916 PUTS "[join $print {, }]." 917 exit 918 } 919 920 if {$config!=""} { 921 if {[llength $config]==1} {lappend config fulltest} 922 set ::CONFIGLIST $config 923 } else { 924 if {$::JOBS>1} { 925 set ::CONFIGLIST {} 926 foreach {target zConfig} [lreverse $::Platforms($platform)] { 927 append ::CONFIGLIST [format " %-25s %s\n" \ 928 [list $zConfig] [list $target]] 929 } 930 } else { 931 set ::CONFIGLIST $::Platforms($platform) 932 } 933 } 934 PUTS "Running the following test configurations for $platform:" 935 PUTS " [string trim $::CONFIGLIST]" 936 PUTSNNL "Flags:" 937 if {$::PROGRESS_MSGS} {PUTSNNL " --progress"} 938 if {$::DRYRUN} {PUTSNNL " --dryrun"} 939 if {$::BUILDONLY} {PUTSNNL " --buildonly"} 940 if {$::MSVC} {PUTSNNL " --msvc"} 941 switch -- $::QUICK { 942 1 {PUTSNNL " --quick"} 943 2 {PUTSNNL " --veryquick"} 944 } 945 if {$::JOBS>1} {PUTSNNL " --jobs $::JOBS"} 946 PUTS "" 947 } 948 949 # Check to see if there are uncommitted changes in the SQLite source 950 # checkout. Exit if there are. Except: Do nothing if the --force 951 # flag is used. Also, ignore this test if the fossil binary is 952 # unavailable, or if the source tree is not a valid fossil checkout. 953 # 954 proc check_uncommitted {} { 955 if {$::FORCE} return 956 set pwd [pwd] 957 cd $::SRCDIR 958 if {[catch {exec fossil changes} res]==0 && [string trim $res]!=""} { 959 puts "ERROR: The check-out contains uncommitted changes:" 960 puts $res 961 puts "Use the -f or --force options to override" 962 exit 1 963 } 964 cd $pwd 965 } 966 967 # A test run has just finished in directory $dir. This command deletes all 968 # non-essential files from the directory. Specifically, everything except 969 # 970 # * The "testfixture" and "sqlite3" binaries, 971 # * The "test-out.log" and "test.log" log files. 972 # 973 proc cleanup {dir} { 974 set K(testfixture) 1 975 set K(testfixture.exe) 1 976 set K(sqlite3) 1 977 set K(sqlite3.exe) 1 978 set K(test-out.txt) 1 979 set K(test.log) 1 980 981 foreach f [glob -nocomplain [file join $dir *]] { 982 set tail [file tail $f] 983 if {[info exists K($tail)]==0} { 984 file delete -force $f 985 } 986 } 987 } 988 989 990 # Main routine. 991 # 992 proc main {argv} { 993 994 # Process any command line options. 995 set ::EXTRACONFIG {} 996 process_options $argv 997 if {!$::DRYRUN} check_uncommitted 998 PUTS [string repeat * 79] 999 1000 set ::NERR 0 1001 set ::NTEST 0 1002 set ::NTESTCASE 0 1003 set ::NERRCASE 0 1004 set ::SQLITE_VERSION {} 1005 set STARTTIME [clock seconds] 1006 foreach {zConfig target} $::CONFIGLIST { 1007 if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target 1008 || "valgrindtest" in $target)} { 1009 PUTS "Skipping $zConfig / $target for MSVC..." 1010 continue 1011 } 1012 if {$target ne "checksymbols"} { 1013 switch -- $::QUICK { 1014 1 {set target quicktest} 1015 2 {set target smoketest} 1016 } 1017 if {$::BUILDONLY} { 1018 set target testfixture 1019 if {$::tcl_platform(platform)=="windows"} { 1020 append target .exe 1021 } 1022 } 1023 } 1024 set config_options [concat $::Configs($zConfig) $::EXTRACONFIG] 1025 1026 incr NTEST 1027 add_test_suite all $zConfig $target $config_options 1028 1029 # If the configuration included the SQLITE_DEBUG option, then remove 1030 # it and run veryquick.test. If it did not include the SQLITE_DEBUG option 1031 # add it and run veryquick.test. 1032 if {$target!="checksymbols" && $target!="valgrindtest" 1033 && $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} { 1034 set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*] 1035 set xtarget $target 1036 regsub -all {fulltest[a-z]*} $xtarget test xtarget 1037 regsub -all {fuzzoomtest} $xtarget fuzztest xtarget 1038 if {$debug_idx < 0} { 1039 incr NTEST 1040 append config_options " -DSQLITE_DEBUG=1 -DSQLITE_EXTRA_IFNULLROW=1" 1041 add_test_suite all "${zConfig}_debug" $xtarget $config_options 1042 } else { 1043 incr NTEST 1044 regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options 1045 regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options 1046 add_test_suite all "${zConfig}_ndebug" $xtarget $config_options 1047 } 1048 } 1049 } 1050 1051 run_all_test_suites $all 1052 1053 set elapsetime [expr {[clock seconds]-$STARTTIME}] 1054 set hr [expr {$elapsetime/3600}] 1055 set min [expr {($elapsetime/60)%60}] 1056 set sec [expr {$elapsetime%60}] 1057 set etime [format (%02d:%02d:%02d) $hr $min $sec] 1058 if {$::JOBS>1} {append etime " $::JOBS cores"} 1059 if {[catch {exec hostname} HNAME]==0} {append etime " on $HNAME"} 1060 PUTS [string repeat * 79] 1061 incr ::NERRCASE $::NERR 1062 PUTS "$::NERRCASE failures out of $::NTESTCASE tests in $etime" 1063 if {$::SQLITE_VERSION ne ""} { 1064 PUTS "SQLite $::SQLITE_VERSION" 1065 } 1066 } 1067 1068 main $argv