OLD | NEW |
(Empty) | |
| 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 |
| 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 } |
| 130 "Fast-One" { |
| 131 -O6 |
| 132 -DSQLITE_ENABLE_FTS4=1 |
| 133 -DSQLITE_ENABLE_RTREE=1 |
| 134 -DSQLITE_ENABLE_STAT4 |
| 135 -DSQLITE_ENABLE_RBU |
| 136 -DSQLITE_MAX_ATTACHED=125 |
| 137 -DLONGDOUBLE_TYPE=double |
| 138 --enable-session |
| 139 } |
| 140 "Device-One" { |
| 141 -O2 |
| 142 -DSQLITE_DEBUG=1 |
| 143 -DSQLITE_DEFAULT_AUTOVACUUM=1 |
| 144 -DSQLITE_DEFAULT_CACHE_SIZE=64 |
| 145 -DSQLITE_DEFAULT_PAGE_SIZE=1024 |
| 146 -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32 |
| 147 -DSQLITE_DISABLE_LFS=1 |
| 148 -DSQLITE_ENABLE_ATOMIC_WRITE=1 |
| 149 -DSQLITE_ENABLE_IOTRACE=1 |
| 150 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 |
| 151 -DSQLITE_MAX_PAGE_SIZE=4096 |
| 152 -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 153 -DSQLITE_OMIT_PROGRESS_CALLBACK=1 |
| 154 -DSQLITE_OMIT_VIRTUALTABLE=1 |
| 155 -DSQLITE_ENABLE_HIDDEN_COLUMNS |
| 156 -DSQLITE_TEMP_STORE=3 |
| 157 --enable-json1 |
| 158 } |
| 159 "Device-Two" { |
| 160 -DSQLITE_4_BYTE_ALIGNED_MALLOC=1 |
| 161 -DSQLITE_DEFAULT_AUTOVACUUM=1 |
| 162 -DSQLITE_DEFAULT_CACHE_SIZE=1000 |
| 163 -DSQLITE_DEFAULT_LOCKING_MODE=0 |
| 164 -DSQLITE_DEFAULT_PAGE_SIZE=1024 |
| 165 -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=1000 |
| 166 -DSQLITE_DISABLE_LFS=1 |
| 167 -DSQLITE_ENABLE_FTS3=1 |
| 168 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 |
| 169 -DSQLITE_ENABLE_RTREE=1 |
| 170 -DSQLITE_MAX_COMPOUND_SELECT=50 |
| 171 -DSQLITE_MAX_PAGE_SIZE=32768 |
| 172 -DSQLITE_OMIT_TRACE=1 |
| 173 -DSQLITE_TEMP_STORE=3 |
| 174 -DSQLITE_THREADSAFE=2 |
| 175 --enable-json1 --enable-fts5 --enable-session |
| 176 } |
| 177 "Locking-Style" { |
| 178 -O2 |
| 179 -DSQLITE_ENABLE_LOCKING_STYLE=1 |
| 180 } |
| 181 "Apple" { |
| 182 -O1 # Avoid a compiler bug in gcc 4.2.1 build 5658 |
| 183 -DHAVE_GMTIME_R=1 |
| 184 -DHAVE_ISNAN=1 |
| 185 -DHAVE_LOCALTIME_R=1 |
| 186 -DHAVE_PREAD=1 |
| 187 -DHAVE_PWRITE=1 |
| 188 -DHAVE_USLEEP=1 |
| 189 -DHAVE_USLEEP=1 |
| 190 -DHAVE_UTIME=1 |
| 191 -DSQLITE_DEFAULT_CACHE_SIZE=1000 |
| 192 -DSQLITE_DEFAULT_CKPTFULLFSYNC=1 |
| 193 -DSQLITE_DEFAULT_MEMSTATUS=1 |
| 194 -DSQLITE_DEFAULT_PAGE_SIZE=1024 |
| 195 -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1 |
| 196 -DSQLITE_ENABLE_API_ARMOR=1 |
| 197 -DSQLITE_ENABLE_AUTO_PROFILE=1 |
| 198 -DSQLITE_ENABLE_FLOCKTIMEOUT=1 |
| 199 -DSQLITE_ENABLE_FTS3=1 |
| 200 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 |
| 201 -DSQLITE_ENABLE_FTS3_TOKENIZER=1 |
| 202 if:os=="Darwin" -DSQLITE_ENABLE_LOCKING_STYLE=1 |
| 203 -DSQLITE_ENABLE_PERSIST_WAL=1 |
| 204 -DSQLITE_ENABLE_PURGEABLE_PCACHE=1 |
| 205 -DSQLITE_ENABLE_RTREE=1 |
| 206 -DSQLITE_ENABLE_SNAPSHOT=1 |
| 207 # -DSQLITE_ENABLE_SQLLOG=1 |
| 208 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 |
| 209 -DSQLITE_MAX_LENGTH=2147483645 |
| 210 -DSQLITE_MAX_VARIABLE_NUMBER=500000 |
| 211 # -DSQLITE_MEMDEBUG=1 |
| 212 -DSQLITE_NO_SYNC=1 |
| 213 -DSQLITE_OMIT_AUTORESET=1 |
| 214 -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 215 -DSQLITE_PREFER_PROXY_LOCKING=1 |
| 216 -DSQLITE_SERIES_CONSTRAINT_VERIFY=1 |
| 217 -DSQLITE_THREADSAFE=2 |
| 218 -DSQLITE_USE_URI=1 |
| 219 -DSQLITE_WRITE_WALFRAME_PREBUFFERED=1 |
| 220 -DUSE_GUARDED_FD=1 |
| 221 -DUSE_PREAD=1 |
| 222 --enable-json1 --enable-fts5 |
| 223 } |
| 224 "Extra-Robustness" { |
| 225 -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1 |
| 226 -DSQLITE_MAX_ATTACHED=62 |
| 227 } |
| 228 "Devkit" { |
| 229 -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 230 -DSQLITE_MAX_ATTACHED=30 |
| 231 -DSQLITE_ENABLE_COLUMN_METADATA |
| 232 -DSQLITE_ENABLE_FTS4 |
| 233 -DSQLITE_ENABLE_FTS5 |
| 234 -DSQLITE_ENABLE_FTS4_PARENTHESIS |
| 235 -DSQLITE_DISABLE_FTS4_DEFERRED |
| 236 -DSQLITE_ENABLE_RTREE |
| 237 --enable-json1 --enable-fts5 |
| 238 } |
| 239 "No-lookaside" { |
| 240 -DSQLITE_TEST_REALLOC_STRESS=1 |
| 241 -DSQLITE_OMIT_LOOKASIDE=1 |
| 242 -DHAVE_USLEEP=1 |
| 243 } |
| 244 "Valgrind" { |
| 245 -DSQLITE_ENABLE_STAT4 |
| 246 -DSQLITE_ENABLE_FTS4 |
| 247 -DSQLITE_ENABLE_RTREE |
| 248 -DSQLITE_ENABLE_HIDDEN_COLUMNS |
| 249 --enable-json1 |
| 250 } |
| 251 |
| 252 # The next group of configurations are used only by the |
| 253 # Failure-Detection platform. They are all the same, but we need |
| 254 # different names for them all so that they results appear in separate |
| 255 # subdirectories. |
| 256 # |
| 257 Fail0 {-O0} |
| 258 Fail2 {-O0} |
| 259 Fail3 {-O0} |
| 260 Fail4 {-O0} |
| 261 FuzzFail1 {-O0} |
| 262 FuzzFail2 {-O0} |
| 263 }] |
| 264 |
| 265 array set ::Platforms [strip_comments { |
| 266 Linux-x86_64 { |
| 267 "Check-Symbols" checksymbols |
| 268 "Fast-One" fuzztest |
| 269 "Debug-One" "mptest test" |
| 270 "Have-Not" test |
| 271 "Secure-Delete" test |
| 272 "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test" |
| 273 "Update-Delete-Limit" test |
| 274 "Extra-Robustness" test |
| 275 "Device-Two" test |
| 276 "No-lookaside" test |
| 277 "Devkit" test |
| 278 "Apple" test |
| 279 "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test} |
| 280 "Device-One" fulltest |
| 281 "Default" "threadtest fulltest" |
| 282 "Valgrind" valgrindtest |
| 283 } |
| 284 Linux-i686 { |
| 285 "Devkit" test |
| 286 "Have-Not" test |
| 287 "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test" |
| 288 "Device-One" test |
| 289 "Device-Two" test |
| 290 "Default" "threadtest fulltest" |
| 291 } |
| 292 Darwin-i386 { |
| 293 "Locking-Style" "mptest test" |
| 294 "Have-Not" test |
| 295 "Apple" "threadtest fulltest" |
| 296 } |
| 297 Darwin-x86_64 { |
| 298 "Locking-Style" "mptest test" |
| 299 "Have-Not" test |
| 300 "Apple" "threadtest fulltest" |
| 301 } |
| 302 "Windows NT-intel" { |
| 303 "Stdcall" test |
| 304 "Have-Not" test |
| 305 "Default" "mptest fulltestonly" |
| 306 } |
| 307 "Windows NT-amd64" { |
| 308 "Stdcall" test |
| 309 "Have-Not" test |
| 310 "Default" "mptest fulltestonly" |
| 311 } |
| 312 |
| 313 # The Failure-Detection platform runs various tests that deliberately |
| 314 # fail. This is used as a test of this script to verify that this script |
| 315 # correctly identifies failures. |
| 316 # |
| 317 Failure-Detection { |
| 318 Fail0 "TEST_FAILURE=0 test" |
| 319 Sanitize "TEST_FAILURE=1 test" |
| 320 Fail2 "TEST_FAILURE=2 valgrindtest" |
| 321 Fail3 "TEST_FAILURE=3 valgrindtest" |
| 322 Fail4 "TEST_FAILURE=4 test" |
| 323 FuzzFail1 "TEST_FAILURE=5 test" |
| 324 FuzzFail2 "TEST_FAILURE=5 valgrindtest" |
| 325 } |
| 326 }] |
| 327 |
| 328 |
| 329 # End of configuration section. |
| 330 ######################################################################### |
| 331 ######################################################################### |
| 332 |
| 333 # Configuration verification: Check that each entry in the list of configs |
| 334 # specified for each platforms exists. |
| 335 # |
| 336 foreach {key value} [array get ::Platforms] { |
| 337 foreach {v t} $value { |
| 338 if {0==[info exists ::Configs($v)]} { |
| 339 puts stderr "No such configuration: \"$v\"" |
| 340 exit -1 |
| 341 } |
| 342 } |
| 343 } |
| 344 |
| 345 # Output log. Disabled for slave interpreters. |
| 346 # |
| 347 if {[lindex $argv end]!="--slave"} { |
| 348 set LOG [open releasetest-out.txt w] |
| 349 proc PUTS {txt} { |
| 350 puts $txt |
| 351 puts $::LOG $txt |
| 352 flush $::LOG |
| 353 } |
| 354 proc PUTSNNL {txt} { |
| 355 puts -nonewline $txt |
| 356 puts -nonewline $::LOG $txt |
| 357 flush $::LOG |
| 358 } |
| 359 proc PUTSERR {txt} { |
| 360 puts stderr $txt |
| 361 puts $::LOG $txt |
| 362 flush $::LOG |
| 363 } |
| 364 puts $LOG "$argv0 $argv" |
| 365 set tm0 [clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S} -gmt 1] |
| 366 puts $LOG "start-time: $tm0 UTC" |
| 367 } else { |
| 368 proc PUTS {txt} { |
| 369 puts $txt |
| 370 } |
| 371 proc PUTSNNL {txt} { |
| 372 puts -nonewline $txt |
| 373 } |
| 374 proc PUTSERR {txt} { |
| 375 puts stderr $txt |
| 376 } |
| 377 } |
| 378 |
| 379 # Open the file $logfile and look for a report on the number of errors |
| 380 # and the number of test cases run. Add these values to the global |
| 381 # $::NERRCASE and $::NTESTCASE variables. |
| 382 # |
| 383 # If any errors occur, then write into $errmsgVar the text of an appropriate |
| 384 # one-line error message to show on the output. |
| 385 # |
| 386 proc count_tests_and_errors {logfile rcVar errmsgVar} { |
| 387 if {$::DRYRUN} return |
| 388 upvar 1 $rcVar rc $errmsgVar errmsg |
| 389 set fd [open $logfile rb] |
| 390 set seen 0 |
| 391 while {![eof $fd]} { |
| 392 set line [gets $fd] |
| 393 if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} { |
| 394 incr ::NERRCASE $nerr |
| 395 incr ::NTESTCASE $ntest |
| 396 set seen 1 |
| 397 if {$nerr>0} { |
| 398 set rc 1 |
| 399 set errmsg $line |
| 400 } |
| 401 } |
| 402 if {[regexp {runtime error: +(.*)} $line all msg]} { |
| 403 # skip over "value is outside range" errors |
| 404 if {[regexp {value .* is outside the range of representable} $line]} { |
| 405 # noop |
| 406 } else { |
| 407 incr ::NERRCASE |
| 408 if {$rc==0} { |
| 409 set rc 1 |
| 410 set errmsg $msg |
| 411 } |
| 412 } |
| 413 } |
| 414 if {[regexp {fatal error +(.*)} $line all msg]} { |
| 415 incr ::NERRCASE |
| 416 if {$rc==0} { |
| 417 set rc 1 |
| 418 set errmsg $msg |
| 419 } |
| 420 } |
| 421 if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} { |
| 422 incr ::NERRCASE |
| 423 if {$rc==0} { |
| 424 set rc 1 |
| 425 set errmsg $all |
| 426 } |
| 427 } |
| 428 if {[regexp {^VERSION: 3\.\d+.\d+} $line]} { |
| 429 set v [string range $line 9 end] |
| 430 if {$::SQLITE_VERSION eq ""} { |
| 431 set ::SQLITE_VERSION $v |
| 432 } elseif {$::SQLITE_VERSION ne $v} { |
| 433 set rc 1 |
| 434 set errmsg "version conflict: {$::SQLITE_VERSION} vs. {$v}" |
| 435 } |
| 436 } |
| 437 } |
| 438 close $fd |
| 439 if {$::BUILDONLY} { |
| 440 incr ::NTESTCASE |
| 441 if {$rc!=0} { |
| 442 set errmsg "Build failed" |
| 443 } |
| 444 } elseif {!$seen} { |
| 445 set rc 1 |
| 446 set errmsg "Test did not complete" |
| 447 if {[file readable core]} { |
| 448 append errmsg " - core file exists" |
| 449 } |
| 450 } |
| 451 } |
| 452 |
| 453 #-------------------------------------------------------------------------- |
| 454 # This command is invoked as the [main] routine for scripts run with the |
| 455 # "--slave" option. |
| 456 # |
| 457 # For each test (i.e. "configure && make test" execution), the master |
| 458 # process spawns a process with the --slave option. It writes two lines |
| 459 # to the slaves stdin. The first contains a single boolean value - the |
| 460 # value of ::TRACE to use in the slave script. The second line contains a |
| 461 # list in the same format as each element of the list passed to the |
| 462 # [run_all_test_suites] command in the master process. |
| 463 # |
| 464 # The slave then runs the "configure && make test" commands specified. It |
| 465 # exits successfully if the tests passes, or with a non-zero error code |
| 466 # otherwise. |
| 467 # |
| 468 proc run_slave_test {} { |
| 469 # Read global vars configuration from stdin. |
| 470 set V [gets stdin] |
| 471 foreach {::TRACE ::MSVC ::DRYRUN ::KEEPFILES} $V {} |
| 472 |
| 473 # Read the test-suite configuration from stdin. |
| 474 set T [gets stdin] |
| 475 foreach {title dir configOpts testtarget makeOpts cflags opts} $T {} |
| 476 |
| 477 # Create and switch to the test directory. |
| 478 set normaldir [file normalize $dir] |
| 479 set ::env(SQLITE_TMPDIR) $normaldir |
| 480 trace_cmd file mkdir $dir |
| 481 trace_cmd cd $dir |
| 482 catch {file delete core} |
| 483 catch {file delete test.log} |
| 484 |
| 485 # Run the "./configure && make" commands. |
| 486 set rc 0 |
| 487 set rc [catch [configureCommand $configOpts]] |
| 488 if {!$rc} { |
| 489 if {[info exists ::env(TCLSH_CMD)]} { |
| 490 set savedEnv(TCLSH_CMD) $::env(TCLSH_CMD) |
| 491 } else { |
| 492 unset -nocomplain savedEnv(TCLSH_CMD) |
| 493 } |
| 494 set ::env(TCLSH_CMD) [file nativename [info nameofexecutable]] |
| 495 set rc [catch [makeCommand $testtarget $makeOpts $cflags $opts]] |
| 496 if {[info exists savedEnv(TCLSH_CMD)]} { |
| 497 set ::env(TCLSH_CMD) $savedEnv(TCLSH_CMD) |
| 498 } else { |
| 499 unset -nocomplain ::env(TCLSH_CMD) |
| 500 } |
| 501 } |
| 502 |
| 503 # Clean up lots of extra files if --keep was not specified. |
| 504 if {$::KEEPFILES==0} { cleanup $normaldir } |
| 505 |
| 506 # Exis successfully if the test passed, or with a non-zero error code |
| 507 # otherwise. |
| 508 exit $rc |
| 509 } |
| 510 |
| 511 # This command is invoked in the master process each time a slave |
| 512 # file-descriptor is readable. |
| 513 # |
| 514 proc slave_fileevent {fd T tm1} { |
| 515 global G |
| 516 foreach {title dir configOpts testtarget makeOpts cflags opts} $T {} |
| 517 |
| 518 if {[eof $fd]} { |
| 519 fconfigure $fd -blocking 1 |
| 520 set rc [catch { close $fd }] |
| 521 |
| 522 set errmsg {} |
| 523 set logfile [file join $dir test.log] |
| 524 if {[file exists $logfile]} { |
| 525 count_tests_and_errors [file join $dir test.log] rc errmsg |
| 526 } elseif {$rc==0 && !$::DRYRUN} { |
| 527 set rc 1 |
| 528 set errmsg "no test.log file..." |
| 529 } |
| 530 |
| 531 if {!$::TRACE} { |
| 532 set tm2 [clock seconds] |
| 533 set hours [expr {($tm2-$tm1)/3600}] |
| 534 set minutes [expr {(($tm2-$tm1)/60)%60}] |
| 535 set seconds [expr {($tm2-$tm1)%60}] |
| 536 set tm [format (%02d:%02d:%02d) $hours $minutes $seconds] |
| 537 |
| 538 if {$rc} { |
| 539 set status FAIL |
| 540 incr ::NERR |
| 541 } else { |
| 542 set status Ok |
| 543 } |
| 544 |
| 545 set n [string length $title] |
| 546 if {$::PROGRESS_MSGS} { |
| 547 PUTS "finished: ${title}[string repeat . [expr {53-$n}]] $status $tm" |
| 548 } else { |
| 549 PUTS "${title}[string repeat . [expr {63-$n}]] $status $tm" |
| 550 } |
| 551 if {$errmsg!=""} {PUTS " $errmsg"} |
| 552 flush stdout |
| 553 } |
| 554 |
| 555 incr G(nJob) -1 |
| 556 } else { |
| 557 set line [gets $fd] |
| 558 if {[string trim $line] != ""} { |
| 559 puts "Trace : $title - \"$line\"" |
| 560 } |
| 561 } |
| 562 } |
| 563 |
| 564 #-------------------------------------------------------------------------- |
| 565 # The only argument passed to this function is a list of test-suites to |
| 566 # run. Each "test-suite" is itself a list consisting of the following |
| 567 # elements: |
| 568 # |
| 569 # * Test title (for display). |
| 570 # * The name of the directory to run the test in. |
| 571 # * The argument for [configureCommand] |
| 572 # * The first argument for [makeCommand] |
| 573 # * The second argument for [makeCommand] |
| 574 # * The third argument for [makeCommand] |
| 575 # |
| 576 proc run_all_test_suites {alltests} { |
| 577 global G |
| 578 set tests $alltests |
| 579 |
| 580 set G(nJob) 0 |
| 581 |
| 582 while {[llength $tests]>0 || $G(nJob)>0} { |
| 583 if {$G(nJob)>=$::JOBS || [llength $tests]==0} { |
| 584 vwait G(nJob) |
| 585 } |
| 586 |
| 587 if {[llength $tests]>0} { |
| 588 set T [lindex $tests 0] |
| 589 set tests [lrange $tests 1 end] |
| 590 foreach {title dir configOpts testtarget makeOpts cflags opts} $T {} |
| 591 if {$::PROGRESS_MSGS && !$::TRACE} { |
| 592 set n [string length $title] |
| 593 PUTS "starting: ${title} at [now]" |
| 594 flush stdout |
| 595 } |
| 596 |
| 597 # Run the job. |
| 598 # |
| 599 set tm1 [clock seconds] |
| 600 incr G(nJob) |
| 601 set script [file normalize [info script]] |
| 602 set fd [open "|[info nameofexecutable] $script --slave" r+] |
| 603 fconfigure $fd -blocking 0 |
| 604 fileevent $fd readable [list slave_fileevent $fd $T $tm1] |
| 605 puts $fd [list $::TRACE $::MSVC $::DRYRUN $::KEEPFILES] |
| 606 puts $fd [list {*}$T] |
| 607 flush $fd |
| 608 } |
| 609 } |
| 610 } |
| 611 |
| 612 proc add_test_suite {listvar name testtarget config} { |
| 613 upvar $listvar alltests |
| 614 |
| 615 # Tcl variable $opts is used to build up the value used to set the |
| 616 # OPTS Makefile variable. Variable $cflags holds the value for |
| 617 # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but |
| 618 # CFLAGS is only passed to gcc. |
| 619 # |
| 620 set makeOpts "" |
| 621 set cflags [expr {$::MSVC ? "-Zi" : "-g"}] |
| 622 set opts "" |
| 623 set title ${name}($testtarget) |
| 624 set configOpts $::WITHTCL |
| 625 set skip 0 |
| 626 |
| 627 regsub -all {#[^\n]*\n} $config \n config |
| 628 foreach arg $config { |
| 629 if {$skip} { |
| 630 set skip 0 |
| 631 continue |
| 632 } |
| 633 if {[regexp {^-[UD]} $arg]} { |
| 634 lappend opts $arg |
| 635 } elseif {[regexp {^[A-Z]+=} $arg]} { |
| 636 lappend testtarget $arg |
| 637 } elseif {[regexp {^if:([a-z]+)(.*)} $arg all key tail]} { |
| 638 # Arguments of the form 'if:os=="Linux"' will cause the subsequent |
| 639 # argument to be skipped if the $tcl_platform(os) is not "Linux", for |
| 640 # example... |
| 641 set skip [expr !(\$::tcl_platform($key)$tail)] |
| 642 } elseif {[regexp {^--(enable|disable)-} $arg]} { |
| 643 if {$::MSVC} { |
| 644 if {$arg eq "--disable-amalgamation"} { |
| 645 lappend makeOpts USE_AMALGAMATION=0 |
| 646 continue |
| 647 } |
| 648 if {$arg eq "--disable-shared"} { |
| 649 lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0 |
| 650 continue |
| 651 } |
| 652 if {$arg eq "--enable-fts5"} { |
| 653 lappend opts -DSQLITE_ENABLE_FTS5 |
| 654 continue |
| 655 } |
| 656 if {$arg eq "--enable-json1"} { |
| 657 lappend opts -DSQLITE_ENABLE_JSON1 |
| 658 continue |
| 659 } |
| 660 if {$arg eq "--enable-shared"} { |
| 661 lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1 |
| 662 continue |
| 663 } |
| 664 } |
| 665 lappend configOpts $arg |
| 666 } else { |
| 667 if {$::MSVC} { |
| 668 if {$arg eq "-g"} { |
| 669 lappend cflags -Zi |
| 670 continue |
| 671 } |
| 672 if {[regexp -- {^-O(\d+)$} $arg all level]} then { |
| 673 lappend makeOpts OPTIMIZATIONS=$level |
| 674 continue |
| 675 } |
| 676 } |
| 677 lappend cflags $arg |
| 678 } |
| 679 } |
| 680 |
| 681 # Disable sync to make testing faster. |
| 682 # |
| 683 lappend opts -DSQLITE_NO_SYNC=1 |
| 684 |
| 685 # Some configurations already set HAVE_USLEEP; in that case, skip it. |
| 686 # |
| 687 if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} { |
| 688 lappend opts -DHAVE_USLEEP=1 |
| 689 } |
| 690 |
| 691 # Add the define for this platform. |
| 692 # |
| 693 if {$::tcl_platform(platform)=="windows"} { |
| 694 lappend opts -DSQLITE_OS_WIN=1 |
| 695 } else { |
| 696 lappend opts -DSQLITE_OS_UNIX=1 |
| 697 } |
| 698 |
| 699 # Set the sub-directory to use. |
| 700 # |
| 701 set dir [string tolower [string map {- _ " " _} $name]] |
| 702 |
| 703 # Join option lists into strings, using space as delimiter. |
| 704 # |
| 705 set makeOpts [join $makeOpts " "] |
| 706 set cflags [join $cflags " "] |
| 707 set opts [join $opts " "] |
| 708 |
| 709 lappend alltests [list \ |
| 710 $title $dir $configOpts $testtarget $makeOpts $cflags $opts] |
| 711 } |
| 712 |
| 713 # The following procedure returns the "configure" command to be exectued for |
| 714 # the current platform, which may be Windows (via MinGW, etc). |
| 715 # |
| 716 proc configureCommand {opts} { |
| 717 if {$::MSVC} return [list]; # This is not needed for MSVC. |
| 718 set result [list trace_cmd exec] |
| 719 if {$::tcl_platform(platform)=="windows"} { |
| 720 lappend result sh |
| 721 } |
| 722 lappend result $::SRCDIR/configure --enable-load-extension |
| 723 foreach x $opts {lappend result $x} |
| 724 lappend result >& test.log |
| 725 } |
| 726 |
| 727 # The following procedure returns the "make" command to be executed for the |
| 728 # specified targets, compiler flags, and options. |
| 729 # |
| 730 proc makeCommand { targets makeOpts cflags opts } { |
| 731 set result [list trace_cmd exec] |
| 732 if {$::MSVC} { |
| 733 set nmakeDir [file nativename $::SRCDIR] |
| 734 set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]] |
| 735 lappend result nmake /f $nmakeFile TOP=$nmakeDir |
| 736 if {[regexp {USE_STDCALL=1} $cflags]} { |
| 737 lappend result USE_STDCALL=1 |
| 738 } |
| 739 } else { |
| 740 lappend result make |
| 741 } |
| 742 foreach makeOpt $makeOpts { |
| 743 lappend result $makeOpt |
| 744 } |
| 745 lappend result clean |
| 746 foreach target $targets { |
| 747 lappend result $target |
| 748 } |
| 749 lappend result CFLAGS=$cflags OPTS=$opts >>& test.log |
| 750 } |
| 751 |
| 752 # The following procedure prints its arguments if ::TRACE is true. |
| 753 # And it executes the command of its arguments in the calling context |
| 754 # if ::DRYRUN is false. |
| 755 # |
| 756 proc trace_cmd {args} { |
| 757 if {$::TRACE} { |
| 758 PUTS $args |
| 759 } |
| 760 set res "" |
| 761 if {!$::DRYRUN} { |
| 762 set res [uplevel 1 $args] |
| 763 } |
| 764 return $res |
| 765 } |
| 766 |
| 767 |
| 768 # This proc processes the command line options passed to this script. |
| 769 # Currently the only option supported is "-makefile", default |
| 770 # "releasetest.mk". Set the ::MAKEFILE variable to the value of this |
| 771 # option. |
| 772 # |
| 773 proc process_options {argv} { |
| 774 set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]] |
| 775 set ::QUICK 0 |
| 776 set ::MSVC 0 |
| 777 set ::BUILDONLY 0 |
| 778 set ::DRYRUN 0 |
| 779 set ::TRACE 0 |
| 780 set ::JOBS 1 |
| 781 set ::PROGRESS_MSGS 0 |
| 782 set ::WITHTCL {} |
| 783 set ::FORCE 0 |
| 784 set ::KEEPFILES 0 ;# Keep extra files after test run |
| 785 set config {} |
| 786 set platform $::tcl_platform(os)-$::tcl_platform(machine) |
| 787 |
| 788 for {set i 0} {$i < [llength $argv]} {incr i} { |
| 789 set x [lindex $argv $i] |
| 790 if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]} |
| 791 switch -glob -- $x { |
| 792 -slave { |
| 793 run_slave_test |
| 794 exit |
| 795 } |
| 796 |
| 797 # Undocumented legacy option: --srcdir DIRECTORY |
| 798 # |
| 799 # DIRECTORY is the root of the SQLite checkout. This sets the |
| 800 # SRCDIR global variable. But that variable is already set |
| 801 # automatically so there really is no reason to have this option. |
| 802 # |
| 803 -srcdir { |
| 804 incr i |
| 805 set ::SRCDIR [file normalize [lindex $argv $i]] |
| 806 } |
| 807 |
| 808 -platform { |
| 809 incr i |
| 810 set platform [lindex $argv $i] |
| 811 } |
| 812 |
| 813 -jobs { |
| 814 incr i |
| 815 set ::JOBS [lindex $argv $i] |
| 816 } |
| 817 |
| 818 -progress { |
| 819 set ::PROGRESS_MSGS 1 |
| 820 } |
| 821 |
| 822 -quick { |
| 823 set ::QUICK 1 |
| 824 } |
| 825 -veryquick { |
| 826 set ::QUICK 2 |
| 827 } |
| 828 |
| 829 -config { |
| 830 incr i |
| 831 set config [lindex $argv $i] |
| 832 } |
| 833 |
| 834 -msvc { |
| 835 set ::MSVC 1 |
| 836 } |
| 837 |
| 838 -buildonly { |
| 839 set ::BUILDONLY 1 |
| 840 } |
| 841 |
| 842 -dryrun { |
| 843 set ::DRYRUN 1 |
| 844 } |
| 845 |
| 846 -force - |
| 847 -f { |
| 848 set ::FORCE 1 |
| 849 } |
| 850 |
| 851 -trace { |
| 852 set ::TRACE 1 |
| 853 } |
| 854 |
| 855 -info { |
| 856 PUTS "Command-line Options:" |
| 857 PUTS " --srcdir $::SRCDIR" |
| 858 PUTS " --platform [list $platform]" |
| 859 PUTS " --config [list $config]" |
| 860 if {$::QUICK} { |
| 861 if {$::QUICK==1} {PUTS " --quick"} |
| 862 if {$::QUICK==2} {PUTS " --veryquick"} |
| 863 } |
| 864 if {$::MSVC} {PUTS " --msvc"} |
| 865 if {$::BUILDONLY} {PUTS " --buildonly"} |
| 866 if {$::DRYRUN} {PUTS " --dryrun"} |
| 867 if {$::TRACE} {PUTS " --trace"} |
| 868 PUTS "\nAvailable --platform options:" |
| 869 foreach y [lsort [array names ::Platforms]] { |
| 870 PUTS " [list $y]" |
| 871 } |
| 872 PUTS "\nAvailable --config options:" |
| 873 foreach y [lsort [array names ::Configs]] { |
| 874 PUTS " [list $y]" |
| 875 } |
| 876 exit |
| 877 } |
| 878 |
| 879 -g { |
| 880 lappend ::EXTRACONFIG [lindex $argv $i] |
| 881 } |
| 882 |
| 883 -keep { |
| 884 set ::KEEPFILES 1 |
| 885 } |
| 886 |
| 887 -with-tcl=* { |
| 888 set ::WITHTCL -$x |
| 889 } |
| 890 |
| 891 -D* - |
| 892 -O* - |
| 893 -enable-* - |
| 894 -disable-* - |
| 895 *=* { |
| 896 lappend ::EXTRACONFIG [lindex $argv $i] |
| 897 } |
| 898 |
| 899 default { |
| 900 PUTSERR "" |
| 901 PUTSERR [string trim $::USAGE_MESSAGE] |
| 902 exit -1 |
| 903 } |
| 904 } |
| 905 } |
| 906 |
| 907 if {0==[info exists ::Platforms($platform)]} { |
| 908 PUTS "Unknown platform: $platform" |
| 909 PUTSNNL "Set the -platform option to " |
| 910 set print [list] |
| 911 foreach p [array names ::Platforms] { |
| 912 lappend print "\"$p\"" |
| 913 } |
| 914 lset print end "or [lindex $print end]" |
| 915 PUTS "[join $print {, }]." |
| 916 exit |
| 917 } |
| 918 |
| 919 if {$config!=""} { |
| 920 if {[llength $config]==1} {lappend config fulltest} |
| 921 set ::CONFIGLIST $config |
| 922 } else { |
| 923 if {$::JOBS>1} { |
| 924 set ::CONFIGLIST {} |
| 925 foreach {target zConfig} [lreverse $::Platforms($platform)] { |
| 926 append ::CONFIGLIST [format " %-25s %s\n" \ |
| 927 [list $zConfig] [list $target]] |
| 928 } |
| 929 } else { |
| 930 set ::CONFIGLIST $::Platforms($platform) |
| 931 } |
| 932 } |
| 933 PUTS "Running the following test configurations for $platform:" |
| 934 PUTS " [string trim $::CONFIGLIST]" |
| 935 PUTSNNL "Flags:" |
| 936 if {$::PROGRESS_MSGS} {PUTSNNL " --progress"} |
| 937 if {$::DRYRUN} {PUTSNNL " --dryrun"} |
| 938 if {$::BUILDONLY} {PUTSNNL " --buildonly"} |
| 939 if {$::MSVC} {PUTSNNL " --msvc"} |
| 940 switch -- $::QUICK { |
| 941 1 {PUTSNNL " --quick"} |
| 942 2 {PUTSNNL " --veryquick"} |
| 943 } |
| 944 if {$::JOBS>1} {PUTSNNL " --jobs $::JOBS"} |
| 945 PUTS "" |
| 946 } |
| 947 |
| 948 # Check to see if there are uncommitted changes in the SQLite source |
| 949 # checkout. Exit if there are. Except: Do nothing if the --force |
| 950 # flag is used. Also, ignore this test if the fossil binary is |
| 951 # unavailable, or if the source tree is not a valid fossil checkout. |
| 952 # |
| 953 proc check_uncommitted {} { |
| 954 if {$::FORCE} return |
| 955 set pwd [pwd] |
| 956 cd $::SRCDIR |
| 957 if {[catch {exec fossil changes} res]==0 && [string trim $res]!=""} { |
| 958 puts "ERROR: The check-out contains uncommitted changes:" |
| 959 puts $res |
| 960 puts "Use the -f or --force options to override" |
| 961 exit 1 |
| 962 } |
| 963 cd $pwd |
| 964 } |
| 965 |
| 966 # A test run has just finished in directory $dir. This command deletes all |
| 967 # non-essential files from the directory. Specifically, everything except |
| 968 # |
| 969 # * The "testfixture" and "sqlite3" binaries, |
| 970 # * The "test-out.log" and "test.log" log files. |
| 971 # |
| 972 proc cleanup {dir} { |
| 973 set K(testfixture) 1 |
| 974 set K(testfixture.exe) 1 |
| 975 set K(sqlite3) 1 |
| 976 set K(sqlite3.exe) 1 |
| 977 set K(test-out.txt) 1 |
| 978 set K(test.log) 1 |
| 979 |
| 980 foreach f [glob -nocomplain [file join $dir *]] { |
| 981 set tail [file tail $f] |
| 982 if {[info exists K($tail)]==0} { |
| 983 file delete -force $f |
| 984 } |
| 985 } |
| 986 } |
| 987 |
| 988 |
| 989 # Main routine. |
| 990 # |
| 991 proc main {argv} { |
| 992 |
| 993 # Process any command line options. |
| 994 set ::EXTRACONFIG {} |
| 995 process_options $argv |
| 996 if {!$::DRYRUN} check_uncommitted |
| 997 PUTS [string repeat * 79] |
| 998 |
| 999 set ::NERR 0 |
| 1000 set ::NTEST 0 |
| 1001 set ::NTESTCASE 0 |
| 1002 set ::NERRCASE 0 |
| 1003 set ::SQLITE_VERSION {} |
| 1004 set STARTTIME [clock seconds] |
| 1005 foreach {zConfig target} $::CONFIGLIST { |
| 1006 if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target |
| 1007 || "valgrindtest" in $target)} { |
| 1008 PUTS "Skipping $zConfig / $target for MSVC..." |
| 1009 continue |
| 1010 } |
| 1011 if {$target ne "checksymbols"} { |
| 1012 switch -- $::QUICK { |
| 1013 1 {set target quicktest} |
| 1014 2 {set target smoketest} |
| 1015 } |
| 1016 if {$::BUILDONLY} { |
| 1017 set target testfixture |
| 1018 if {$::tcl_platform(platform)=="windows"} { |
| 1019 append target .exe |
| 1020 } |
| 1021 } |
| 1022 } |
| 1023 set config_options [concat $::Configs($zConfig) $::EXTRACONFIG] |
| 1024 |
| 1025 incr NTEST |
| 1026 add_test_suite all $zConfig $target $config_options |
| 1027 |
| 1028 # If the configuration included the SQLITE_DEBUG option, then remove |
| 1029 # it and run veryquick.test. If it did not include the SQLITE_DEBUG option |
| 1030 # add it and run veryquick.test. |
| 1031 if {$target!="checksymbols" && $target!="valgrindtest" |
| 1032 && $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} { |
| 1033 set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*] |
| 1034 set xtarget $target |
| 1035 regsub -all {fulltest[a-z]*} $xtarget test xtarget |
| 1036 regsub -all {fuzzoomtest} $xtarget fuzztest xtarget |
| 1037 if {$debug_idx < 0} { |
| 1038 incr NTEST |
| 1039 append config_options " -DSQLITE_DEBUG=1" |
| 1040 add_test_suite all "${zConfig}_debug" $xtarget $config_options |
| 1041 } else { |
| 1042 incr NTEST |
| 1043 regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options |
| 1044 regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options |
| 1045 add_test_suite all "${zConfig}_ndebug" $xtarget $config_options |
| 1046 } |
| 1047 } |
| 1048 } |
| 1049 |
| 1050 run_all_test_suites $all |
| 1051 |
| 1052 set elapsetime [expr {[clock seconds]-$STARTTIME}] |
| 1053 set hr [expr {$elapsetime/3600}] |
| 1054 set min [expr {($elapsetime/60)%60}] |
| 1055 set sec [expr {$elapsetime%60}] |
| 1056 set etime [format (%02d:%02d:%02d) $hr $min $sec] |
| 1057 if {$::JOBS>1} {append etime " $::JOBS cores"} |
| 1058 if {[catch {exec hostname} HNAME]==0} {append etime " on $HNAME"} |
| 1059 PUTS [string repeat * 79] |
| 1060 incr ::NERRCASE $::NERR |
| 1061 PUTS "$::NERRCASE failures out of $::NTESTCASE tests in $etime" |
| 1062 if {$::SQLITE_VERSION ne ""} { |
| 1063 PUTS "SQLite $::SQLITE_VERSION" |
| 1064 } |
| 1065 } |
| 1066 |
| 1067 main $argv |
OLD | NEW |