diff --git a/ext/recover/recover1.test b/ext/recover/recover1.test index 3e8a691492..fef1bf90f4 100644 --- a/ext/recover/recover1.test +++ b/ext/recover/recover1.test @@ -275,11 +275,13 @@ do_recover_test 15 #------------------------------------------------------------------------- reset_db -do_execsql_test 16.1 { - PRAGMA journal_mode = wal; - CREATE TABLE t1(x); - INSERT INTO t1 VALUES(1), (2), (3); -} {wal} +do_test 16.1 { + execsql { PRAGMA journal_mode = wal } + execsql { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1), (2), (3); + } +} {} do_test 16.2 { set R [sqlite3_recover_init db main test.db2] $R run diff --git a/ext/rtree/rtreecheck.test b/ext/rtree/rtreecheck.test index 1754ff5c3d..ff5397e1e1 100644 --- a/ext/rtree/rtreecheck.test +++ b/ext/rtree/rtreecheck.test @@ -167,9 +167,18 @@ do_execsql_test 6.0 { } db close sqlite3 db test.db -do_catchsql_test 6.1 { - SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1; -} {1 {database table is locked}} + +if {[permutation]=="inmemory_journal"} { + # This doesn't hit an SQLITE_LOCKED in this permutation as the schema + # has already been loaded. + do_catchsql_test 6.1.inmemory_journal { + SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1; + } {0 0} +} else { + do_catchsql_test 6.1 { + SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1; + } {1 {database table is locked}} +} finish_test diff --git a/manifest b/manifest index 07add447dc..669b7f9aab 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Better\serror\smessage\swhen\strying\sto\sdo\san\sINSERT\son\san\ssqlite_dbpage\svirtual\ntable. -D 2023-02-04T14:23:26.691 +C Updates\sto\sthe\stestrunner.tcl\sscript\sso\sthat\suses\sa\sseparate\ssub-process\sfor\seach\stest.\sAnd\sso\sthat\sit\sruns\sthe\srelease\stest\sprocedure\scurrently\shandled\sby\swapptest.tcl. +D 2023-02-04T19:01:17.591 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -366,7 +366,7 @@ F ext/rbu/sqlite3rbu.c 348bb6251e6ec459de102f8b2dd50789a98643ef7a28e56e4c787ac96 F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304 F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055 F ext/recover/dbdata.c dc25628e405c86936c597e28f3e6f56a257029c3034c5ef7f6b10f7c02f41018 -F ext/recover/recover1.test 2a2df2943d6696f9487e75868feae4b1511c4a511b102854ba0d2af0326d9dfb +F ext/recover/recover1.test 2072993624d5e32fef20ae03b17fc06c02bcb344421fe17bb329b24d2a51e647 F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49 @@ -414,7 +414,7 @@ F ext/rtree/rtreeH.test 0885151ee8429242625600ae47142cca935332c70a06737f35af53a7 F ext/rtree/rtreeI.test 608e77f7fde9be5a12eae316baef640fffaafcfa90a3d67443e78123e19c4ca4 F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed -F ext/rtree/rtreecheck.test e53fc47fb727d7ffa17ea79fecfe3e709815b65233c11464a0b8f1f4ac0cb50a +F ext/rtree/rtreecheck.test 4e859a9cd49d2353ff10c122f72183ec37b400e35d2b0349b2e9696649b6a00e F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d F ext/rtree/rtreedoc.test 27a5703cb1200f6f69051de68da546cef3dfdcf59be73afadfc50b9f9c9960d9 @@ -676,7 +676,7 @@ F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939 F src/test_tclsh.c 7dd98be675a1dc0d1fd302b8247bab992c909db384df054381a2279ad76f9b0e F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc -F src/test_thread.c 269ea9e1fa5828dba550eb26f619aa18aedbc29fd92f8a5f6b93521fbb74a61c +F src/test_thread.c 7ddcf0c8b79fa3c1d172f82f322302c963d923cdb503c6171f3c8081586d0b01 F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43 F src/test_vfs.c 193c18da3dbf62a0e33ae7a240bbef938a50846672ee947664512b77d853fe81 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 @@ -937,7 +937,7 @@ F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a199 F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e F test/distinct.test a7687c2fb50c93f6a486936c51439a93221c6e1188f9bc7b27b3ec26f9c58b1e F test/distinct2.test cd1d15a4a2abf579298f7161e821ed50c0119136fe0424db85c52cf0adc230d1 -F test/distinctagg.test d76ef2e91fe810630c176d6bd0a58c14d5851c3125f0a1d977db87ba76359639 +F test/distinctagg.test 14ec5026e684eddd414c61c08692b43773e224ac92efbed6ec08c6994bc39723 F test/e_blobbytes.test 4c01dfe4f12087b92b20705a3fdfded45dc4ed16d5a211fed4e1d2786ba68a52 F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d540ac2e075 F test/e_blobopen.test 29f6055ee453b8e679fe9570c4d3acfedbef821622c5dad16875148c5952ef50 @@ -1361,7 +1361,7 @@ F test/ossfuzz.c 9636dad2092a05a32110df0ca06713038dd0c43dd89a77dabe4b8b0d7109671 F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17 F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f F test/pager1.test ffd885cdc98b986c9f746496508c0c4810ed0eaade3575ddf53c222e85880552 -F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 +F test/pager2.test 57ce815e31a7509fcdf7c5474577fd2e9cfee1281d45601e0f7a3bd5534d70a4 F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370 F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e F test/pagerfault.test 63c5da625562c66345ab4528790327ca63db2f6f9cbae2aba8cb7c51de3d1628 @@ -1374,7 +1374,7 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/pendingrace.test fb997b46d6c144a508fb8025d988a1e511b53d42d24143c57b51de3a405c7490 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test 4705a032bbfef531bb3fd98b8c6ba4a739998949eae9ac0ea97c8696b331211d +F test/permutations.test 8bd6b6db541e2a7f9bb894be99ef5c00526b23762c4a00c574e1cba697495125 F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f F test/pragma.test a74a9c9642e5d7e32f5a2aa77a2ed64ec5b69fecff39d52c4daf5945a2a4de65 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f @@ -1403,7 +1403,7 @@ F test/recover.test fd5199f928757cb308661b5fdca1abc19398a798ff7f24b57c3071e9f8e0 F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1 F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5 F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d -F test/releasetest_data.tcl 0db8aee0c348090fd06da47020ab4ed8ec692e0723427b2f3947d4dfb806f3b0 +F test/releasetest_data.tcl b550dd1b122a9c969df794d05ea272df535f10ff1a245062e7ba080822378016 F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/returning1.test 3ef7b264598b3292be0cdb028e4acb7524c5fd409b33b78449f894dfd68db334 @@ -1509,7 +1509,7 @@ F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 F test/sort.test f86751134159abb5e5fd4381a0d7038c91013638cd1e3fa1d7850901f6df6196 F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0 F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5 -F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c +F test/sort4.test cca6f4b0b5255882645bbbe346a6a9f4a5c7b6a18513a6a7bf4ac1c4761ddc19 F test/sort5.test 6b43ae0e2169b5ceed441844492e55ba7f1ae0790528395ddf7888ab3094525d F test/sorterref.test 9a606c86a4c682db5eeaaefa0565b52102778db53e48ca7101cd4f9ebcc0ad94 F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66 @@ -1565,8 +1565,9 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16 F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637 F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc -F test/tester.tcl e72c337f01e47c2833c83288b60e0a1730165cc7de7b59724e925c4ce026c0a1 -F test/testrunner.tcl 407fc02be0c859ef7a85b9431de9c5aa79363cab822ecbee3500a0daeb6b82cd +F test/tester.tcl 8d54d40a55e12554b4509bc12078b201b233c8e842a7543629094a21b1ba956d +F test/testrunner.tcl d897f93dd316f3f01449632b5342534b8cf0e63e4131fa3f540086819a9055c1 +F test/testrunner_data.tcl 8169c68654ac8906833b8a6aadca973358a441ebf88270dd05c153e5f96f76b8 F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899 F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1802,7 +1803,7 @@ F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487 F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679 F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456 -F test/vt02.c 33ecddc0832d4cd24e9e9fa83d868981b1e049462f4ec9080710353f6479a534 +F test/vt02.c 86253b57d6bc2170dfca33f45fd099b66d0bf874e95ecd7786dcbb134f179469 F test/vtab1.test 09a72330d0f31eda2ffaa828b06a6b917fb86250ee72de0301570af725774c07 F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e @@ -1912,7 +1913,7 @@ F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45f1ed F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836 F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be -F test/windowB.test 57f9fb931ed5e04f17db4fcb7059e76026079daf451aac27e54d41217078039b +F test/windowB.test cf1278912c7a059763c49cbd6e1b3213b5e9b9d87a5b22714c63808fc33bc8d5 F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2 F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b F test/windowE.test 6ba0c8048e4cc02b942e56640f8fcd50fd7ca72c876656c40f6baf42e316684c @@ -2047,8 +2048,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 35bed981416269018a0d52171d9997c43d3b097f5db1910d10d882eabe2e137f -R 7386f09ea9b1844db9d9a8f334747060 -U drh -Z 9008008dfbb3677f903fa2808a7570c9 +P a98e4908dabc8f45f7859a26bd1d0c04de34ec68c1367c2cdd9b0242e08b938f 7624de3a93e03e9e825b1a283ccde8ad3aa41f93dd5c7f63692620a5177cbda9 +R b23b921e204f6eaaf5ec2663c7720a91 +T +closed 7624de3a93e03e9e825b1a283ccde8ad3aa41f93dd5c7f63692620a5177cbda9 +U dan +Z 92f5ffe758031c7babad159f1502cbcd # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e2e70b2d84..7624942022 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a98e4908dabc8f45f7859a26bd1d0c04de34ec68c1367c2cdd9b0242e08b938f \ No newline at end of file +4c3c587500ac5a3758008f0acb9432bd3bc6f0f31bacd5615f46280e55842982 \ No newline at end of file diff --git a/src/test_thread.c b/src/test_thread.c index de0fdb4346..126fd98369 100644 --- a/src/test_thread.c +++ b/src/test_thread.c @@ -384,6 +384,27 @@ static int SQLITE_TCLAPI clock_seconds_proc( return TCL_OK; } +/* +** The [clock_milliseconds] command. This is more or less the same as the +** regular tcl [clock milliseconds]. +*/ +static int SQLITE_TCLAPI clock_milliseconds_proc( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_Time now; + Tcl_GetTime(&now); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj( + ((Tcl_WideInt)now.sec * 1000) + (now.usec / 1000) + )); + UNUSED_PARAMETER(clientData); + UNUSED_PARAMETER(objc); + UNUSED_PARAMETER(objv); + return TCL_OK; +} + /************************************************************************* ** This block contains the implementation of the [sqlite3_blocking_step] ** command available to threads created by [sqlthread spawn] commands. It @@ -617,15 +638,26 @@ static int SQLITE_TCLAPI blocking_prepare_v2_proc( ** Register commands with the TCL interpreter. */ int SqlitetestThread_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, 0, 0); - Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0); + struct TclCmd { + int (*xProc)(void*, Tcl_Interp*, int, Tcl_Obj*const*); + const char *zName; + int iCtx; + } aCmd[] = { + { sqlthread_proc, "sqlthread", 0 }, + { clock_seconds_proc, "clock_second", 0 }, + { clock_milliseconds_proc, "clock_milliseconds", 0 }, #if SQLITE_OS_UNIX && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) - Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0); - Tcl_CreateObjCommand(interp, - "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc, (void *)1, 0); - Tcl_CreateObjCommand(interp, - "sqlite3_nonblocking_prepare_v2", blocking_prepare_v2_proc, 0, 0); + { blocking_step_proc, "sqlite3_blocking_step", 0 }, + { blocking_prepare_v2_proc, "sqlite3_blocking_prepare_v2", 1 }, + { blocking_prepare_v2_proc, "sqlite3_nonblocking_prepare_v2", 0 }, #endif + }; + int ii; + + for(ii=0; ii3} { + usage + } + set config [lindex $args end-1] + set srcdir [lindex $args end] + + set opts [list] ;# OPTS value + set cflags [expr {$bMsvc ? "-Zi" : "-g"}] ;# CFLAGS value + set makeOpts [list] ;# Extra args for [make] + set configOpts [list] ;# Extra args for [configure] + + if {$::tcl_platform(platform)=="windows" || $bMsvc} { + lappend opts -DSQLITE_OS_WIN=1 + } else { + lappend opts -DSQLITE_OS_UNIX=1 + } + + # Figure out if this is a synthetic ndebug or debug configuration. + # + set bRemoveDebug 0 + if {[string match *-ndebug $config]} { + set bRemoveDebug 1 + set config [string range $config 0 end-7] + } + if {[string match *-debug $config]} { + lappend opts -DSQLITE_DEBUG + lappend opts -DSQLITE_EXTRA_IFNULLROW + set config [string range $config 0 end-6] + } + regexp {^(.*)-[0-9]+} $config -> config + + # Ensure that the named configuration exists. + # + if {![info exists ::Configs($config)]} { + puts stderr "No such config: $config" + exit 1 + } + + # Loop through the parameters of the nominated configuration, updating + # $opts, $cflags, $makeOpts and $configOpts along the way. Rules are as + # follows: + # + # 1. If the parameter begins with a "*", discard it. + # + # 2. If $bRemoveDebug is set and the parameter is -DSQLITE_DEBUG or + # -DSQLITE_DEBUG=1, discard it + # + # 3. If the parameter begins with "-D", add it to $opts. + # + # 4. If the parameter begins with "--" add it to $configOpts. Unless + # this command is preparing a script for MSVC - then add an + # equivalent to $makeOpts or $opts. + # + # 5. If the parameter begins with "-" add it to $cflags. If in MSVC + # mode and the parameter is an -O option, instead add + # an OPTIMIZATIONS= switch to $makeOpts. + # + # 6. If none of the above apply, add the parameter to $makeOpts + # + foreach param $::Configs($config) { + if {[string range $param 0 0]=="*"} continue + + if {$bRemoveDebug} { + if {$param=="-DSQLITE_DEBUG" || $param=="-DSQLITE_DEBUG=1" + || $param=="-DSQLITE_MEMDEBUG" || $param=="-DSQLITE_MEMDEBUG=1" + || $param=="--enable-debug" + } { + continue + } + } + + if {[string range $param 0 1]=="-D"} { + lappend opts $param + continue + } + + if {[string range $param 0 1]=="--"} { + if {$bMsvc} { + switch -- $param { + --disable-amalgamation { + lappend makeOpts USE_AMALGAMATION=0 + } + --disable-shared { + lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0 + } + --enable-fts5 { + lappend opts -DSQLITE_ENABLE_FTS5 + } + --enable-shared { + lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1 + } + --enable-session { + lappend opts -DSQLITE_ENABLE_PREUPDATE_HOOK + lappend opts -DSQLITE_ENABLE_SESSION + } + default { + error "Cannot translate $param for MSVC" + } + } + } else { + lappend configOpts $param + } + + continue + } + + if {[string range $param 0 0]=="-"} { + if {$bMsvc && [regexp -- {^-O(\d+)$} $param -> level]} { + lappend makeOpts OPTIMIZATIONS=$level + } else { + lappend cflags $param + } + continue + } + + lappend makeOpts $param + } + + # Some configurations specify -DHAVE_USLEEP=0. For all others, add + # -DHAVE_USLEEP=1. + # + if {[lsearch $opts "-DHAVE_USLEEP=0"]<0} { + lappend opts -DHAVE_USLEEP=1 + } + + if {$bMsvc==0} { + puts {set -e} + puts {} + puts {if [ "$#" -ne 1 ] ; then} + puts { echo "Usage: $0 " } + puts { exit -1 } + puts {fi } + puts "SRCDIR=\"$srcdir\"" + puts {} + puts "TCL=\"[::tcl::pkgconfig get libdir,install]\"" + + puts {if [ ! -f Makefile ] ; then} + puts " \$SRCDIR/configure --with-tcl=\$TCL $configOpts" + puts {fi} + puts {} + puts {OPTS=" -DSQLITE_NO_SYNC=1"} + foreach o $opts { + puts "OPTS=\"\$OPTS $o\"" + } + puts {} + puts "CFLAGS=\"$cflags\"" + puts {} + puts "make \$1 \"CFLAGS=\$CFLAGS\" \"OPTS=\$OPTS\" $makeOpts" + } else { + + set srcdir [file nativename [file normalize $srcdir]] + # set srcdir [string map [list "\\" "\\\\"] $srcdir] + + puts {set TARGET=%1} + set makecmd "nmake /f $srcdir\\Makefile.msc TOP=\"$srcdir\" %TARGET% " + append makecmd "\"CFLAGS=$cflags\" \"OPTS=$opts\" $makeOpts" + + puts "set TMP=%CD%" + puts $makecmd + } +} + proc main_tests {args} { set bNodebug 0 set nArg [llength $args] @@ -648,6 +816,8 @@ if {[string match ${cmd}* configurations] && $n==0} { main_configurations } elseif {[string match ${cmd}* script]} { main_script {*}[lrange $argv 1 end] +} elseif {[string match ${cmd}* trscript]} { + main_trscript {*}[lrange $argv 1 end] } elseif {[string match ${cmd}* platforms] && $n==0} { main_platforms } elseif {[string match ${cmd}* tests]} { diff --git a/test/sort4.test b/test/sort4.test index 13d9a5999a..84125885ab 100644 --- a/test/sort4.test +++ b/test/sort4.test @@ -8,6 +8,8 @@ # May you share freely, never taking more than you give. # #*********************************************************************** +# TESTRUNNER: superslow +# # This file implements regression tests for SQLite library. # # The tests in this file are brute force tests of the multi-threaded diff --git a/test/tester.tcl b/test/tester.tcl index 022dad900d..4658590cf4 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -552,6 +552,7 @@ if {[info exists cmdlinearg]==0} { } } } + unset -nocomplain a set testdir [file normalize $testdir] set cmdlinearg(TESTFIXTURE_HOME) [pwd] set cmdlinearg(INFO_SCRIPT) [file normalize [info script]] @@ -1318,9 +1319,11 @@ proc finalize_testing {} { if {$::cmdlinearg(binarylog)} { vfslog finalize binarylog } - if {$sqlite_open_file_count} { - output2 "$sqlite_open_file_count files were left open" - incr nErr + if {[info exists ::run_thread_tests_called]==0} { + if {$sqlite_open_file_count} { + output2 "$sqlite_open_file_count files were left open" + incr nErr + } } if {[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]>0 || [sqlite3_memory_used]>0} { @@ -2502,8 +2505,10 @@ proc test_restore_config_pagecache {} { catch {db3 close} sqlite3_shutdown - eval sqlite3_config_pagecache $::old_pagecache_config - unset ::old_pagecache_config + if {[info exists ::old_pagecache_config]} { + eval sqlite3_config_pagecache $::old_pagecache_config + unset ::old_pagecache_config + } sqlite3_initialize autoinstall_test_functions sqlite3 db test.db diff --git a/test/testrunner.tcl b/test/testrunner.tcl index 48afff47e6..0522391b3d 100644 --- a/test/testrunner.tcl +++ b/test/testrunner.tcl @@ -1,87 +1,61 @@ +set dir [pwd] +set testdir [file dirname $argv0] +set saved $argv +set argv [list] +source [file join $testdir testrunner_data.tcl] +source [file join $testdir permutations.test] +set argv $saved +cd $dir + #------------------------------------------------------------------------- # Usage: # proc usage {} { - set a0 testrunner.tcl + set a0 [file tail $::argv0] - set ::argv [list] - uplevel [list source $::testdir/permutations.test] + puts stderr [string trim [subst -nocommands { +Usage: + $a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS? + $a0 PERMUTATION FILE + $a0 njob ?NJOB? + $a0 status - puts stderr "Usage: $a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?" - puts stderr "" - puts stderr "where SWITCHES are:" - puts stderr " --jobs NUMBER-OF-JOBS" - puts stderr "" - puts stderr "available PERMUTATION values are:" - set ii 0 - foreach name [lsort [array names ::testspec]] { - if {($ii % 3)==0} { puts -nonewline stderr " " } - puts -nonewline stderr [format "% -22s" $name] - if {($ii % 3)==2} { puts stderr "" } - incr ii - } - puts stderr "" - puts stderr "" - puts stderr "Examples:" - puts stderr " 1) Run the veryquick tests:" - puts stderr " $a0" - puts stderr " 2) Run all test scripts in the source tree:" - puts stderr " $a0 full" - puts stderr " 2) Run the 'memsubsys1' permutation:" - puts stderr " $a0 memsubsys1" - puts stderr " 3) Run all permutations usually run by \[make fulltest\]" - puts stderr " $a0 release" - puts stderr " 4) Run all scripts that match the pattern 'select%':" - puts stderr " $a0 select%" - puts stderr " $a0 all select%" - puts stderr " $a0 full select%" - puts stderr " 5) Run all scripts that are part of the veryquick permutation and match the pattern 'select%':" - puts stderr " $a0 veryquick select%" - puts stderr " 6) Run the 'memsubsys1' permutation, but just those scripts that match 'window%':" - puts stderr " $a0 memsubsys1 window%" - puts stderr " 7) Run all the permutations, but only the scripts that match either 'fts5%' or 'rtree%':" - puts stderr " $a0 release fts5% rtree%" + where SWITCHES are: + --jobs NUMBER-OF-JOBS + +Interesting values for PERMUTATION are: + + veryquick - a fast subset of the tcl test scripts. This is the default. + full - all tcl test scripts. + all - all tcl test scripts, plus a subset of test scripts rerun + with various permutations. + release - full release test with various builds. + +If no PATTERN arguments are present, all tests specified by the PERMUTATION +are run. Otherwise, each pattern is interpreted as a glob pattern. Only +those tcl tests for which the final component of the filename matches at +least one specified pattern are run. + +If no PATTERN arguments are present, then various fuzztest, threadtest +and other tests are run as part of the "release" permutation. These are +omitted if any PATTERN arguments are specified on the command line. + +If a PERMUTATION is specified and is followed by the path to a Tcl script +instead of a list of patterns, then that single Tcl test script is run +with the specified permutation. + +The "status" and "njob" commands are designed to be run from the same +directory as a running testrunner.tcl script that is running tests. The +"status" command prints a report describing the current state and progress +of the tests. The "njob" command may be used to query or modify the number +of sub-processes the test script uses to run tests. + }]] exit 1 } #------------------------------------------------------------------------- -#------------------------------------------------------------------------- -# The database schema used by the testrunner.db database. -# -set R(schema) { - DROP TABLE IF EXISTS script; - DROP TABLE IF EXISTS msg; - DROP TABLE IF EXISTS malloc; - - CREATE TABLE script( - config TEXT, - filename TEXT, -- full path to test script - slow BOOLEAN, -- true if script is "slow" - state TEXT CHECK( state IN ('ready', 'running', 'done') ), - testfixtureid, -- Id of process that ran script - time INTEGER, -- Time in ms - nerr INTEGER, -- if 'done', the number of errors - ntest INTEGER, -- if 'done', the number of tests - output TEXT, -- full output of test script - PRIMARY KEY(config, filename) - ); - - CREATE TABLE malloc( - id INTEGER PRIMARY KEY, - nmalloc INTEGER, - nbyte INTEGER, - leaker TEXT - ); - - CREATE TABLE msg( - id INTEGER PRIMARY KEY, - msg TEXT - ); -} -#------------------------------------------------------------------------- - #------------------------------------------------------------------------- # Try to estimate a the number of processes to use. # @@ -113,593 +87,741 @@ proc default_njob {} { } #------------------------------------------------------------------------- +#------------------------------------------------------------------------- +# Setup various default values in the global TRG() array. +# +set TRG(dbname) [file normalize testrunner.db] +set TRG(logname) [file normalize testrunner.log] +set TRG(build.logname) [file normalize testrunner_build.log] +set TRG(info_script) [file normalize [info script]] +set TRG(timeout) 10000 ;# Default busy-timeout for testrunner.db +set TRG(nJob) [default_njob] ;# Default number of helper processes +set TRG(patternlist) [list] +set TRG(cmdline) $argv +set TRG(reporttime) 2000 -set R(dbname) [file normalize testrunner.db] -set R(logname) [file normalize testrunner.log] -set R(info_script) [file normalize [info script]] -set R(timeout) 10000 ;# Default busy-timeout for testrunner.db -set R(nJob) [default_njob] ;# Default number of helper processes -set R(leaker) "" ;# Name of first script to leak memory +switch -nocase -glob -- $tcl_platform(os) { + *darwin* { + set TRG(platform) osx + set TRG(make) make.sh + set TRG(makecmd) "bash make.sh" + } + *linux* { + set TRG(platform) linux + set TRG(make) make.sh + set TRG(makecmd) "bash make.sh" + } + *win* { + set TRG(platform) win + set TRG(make) make.bat + set TRG(makecmd) make.bat + } + default { + error "cannot determine platform!" + } +} +#------------------------------------------------------------------------- -set R(patternlist) [list] +#------------------------------------------------------------------------- +# The database schema used by the testrunner.db database. +# +set TRG(schema) { + DROP TABLE IF EXISTS script; + DROP TABLE IF EXISTS config; + + CREATE TABLE script( + build TEXT DEFAULT '', + config TEXT, + filename TEXT, -- full path to test script + slow BOOLEAN, -- true if script is "slow" + state TEXT CHECK( state IN ('', 'ready', 'running', 'done', 'failed') ), + time INTEGER, -- Time in ms + output TEXT, -- full output of test script + priority AS ((config='make') + ((config='build')*2) + (slow*4)), + jobtype AS ( + CASE WHEN config IN ('build', 'make') THEN config ELSE 'script' END + ), + PRIMARY KEY(build, config, filename) + ); + + CREATE TABLE config( + name TEXT COLLATE nocase PRIMARY KEY, + value + ) WITHOUT ROWID; + + CREATE INDEX i1 ON script(state, jobtype); + CREATE INDEX i2 ON script(state, priority); +} +#------------------------------------------------------------------------- + +#-------------------------------------------------------------------------- +# Check if this script is being invoked to run a single file. If so, +# run it. +# +if {[llength $argv]==2 + && ([lindex $argv 0]=="" || [info exists ::testspec([lindex $argv 0])]) + && [file exists [lindex $argv 1]] +} { + set permutation [lindex $argv 0] + set script [file normalize [lindex $argv 1]] + set ::argv [list] + + if {$permutation=="full"} { + + set testdir [file dirname $argv0] + source $::testdir/tester.tcl + unset -nocomplain ::G(isquick) + reset_db + + } elseif {$permutation!="default" && $permutation!=""} { + + if {[info exists ::testspec($permutation)]==0} { + error "no such permutation: $permutation" + } + + array set O $::testspec($permutation) + set ::G(perm:name) $permutation + set ::G(perm:prefix) $O(-prefix) + set ::G(isquick) 1 + set ::G(perm:dbconfig) $O(-dbconfig) + set ::G(perm:presql) $O(-presql) + + rename finish_test helper_finish_test + proc finish_test {} " + uplevel { + $O(-shutdown) + } + helper_finish_test + " + + eval $O(-initialize) + } + + reset_db + source $script + exit +} +#-------------------------------------------------------------------------- + +#-------------------------------------------------------------------------- +# Check if this is the "njob" command: +# +if {([llength $argv]==2 || [llength $argv]==1) + && [string compare -nocase njob [lindex $argv 0]]==0 +} { + sqlite3 mydb $TRG(dbname) + if {[llength $argv]==2} { + set param [lindex $argv 1] + if {[string is integer $param]==0 || $param<1 || $param>128} { + puts stderr "parameter must be an integer between 1 and 128" + exit 1 + } + + mydb eval { REPLACE INTO config VALUES('njob', $param); } + } + set res [mydb one { SELECT value FROM config WHERE name='njob' }] + mydb close + puts "$res" + exit +} +#-------------------------------------------------------------------------- + +#-------------------------------------------------------------------------- +# Check if this is the "status" command: +# +if {[llength $argv]==1 + && [string compare -nocase status [lindex $argv 0]]==0 +} { + + proc display_job {build config filename {tm ""}} { + if {$config=="build"} { + set fname "build: $filename" + set config "" + } elseif {$config=="make"} { + set fname "make: $filename" + set config "" + } else { + set fname [file normalize $filename] + if {[string first $::srcdir $fname]==0} { + set fname [string range $fname [string length $::srcdir]+1 end] + } + } + set dfname [format %-33s $fname] + + set dbuild "" + set dconfig "" + set dparams "" + set dtm "" + if {$build!=""} { set dbuild $build } + if {$config!="" && $config!="full"} { set dconfig $config } + if {$dbuild!="" || $dconfig!=""} { + append dparams "(" + if {$dbuild!=""} {append dparams "build=$dbuild"} + if {$dbuild!="" && $dconfig!=""} {append dparams " "} + if {$dconfig!=""} {append dparams "config=$dconfig"} + append dparams ")" + set dparams [format %-33s $dparams] + } + if {$tm!=""} { + set dtm "\[${tm}ms\]" + } + puts " $dfname $dparams $dtm" + } + + sqlite3 mydb $TRG(dbname) + mydb timeout 1000 + mydb eval BEGIN + + set cmdline [mydb one { SELECT value FROM config WHERE name='cmdline' }] + set nJob [mydb one { SELECT value FROM config WHERE name='njob' }] + set tm [expr [clock_milliseconds] - [mydb one { + SELECT value FROM config WHERE name='start' + }]] + + set total 0 + foreach s {"" ready running done failed} { set S($s) 0 } + mydb eval { + SELECT state, count(*) AS cnt FROM script GROUP BY 1 + } { + incr S($state) $cnt + incr total $cnt + } + set fin [expr $S(done)+$S(failed)] + if {$cmdline!=""} {set cmdline " $cmdline"} + + set f "" + if {$S(failed)>0} { + set f "$S(failed) FAILED, " + } + puts "Command line: \[testrunner.tcl$cmdline\]" + puts "Jobs: $nJob" + puts "Summary: ${tm}ms, ($fin/$total) finished, ${f}$S(running) running" + + set srcdir [file dirname [file dirname $TRG(info_script)]] + if {$S(running)>0} { + puts "Running: " + set now [clock_milliseconds] + mydb eval { + SELECT build, config, filename, time FROM script WHERE state='running' + ORDER BY time + } { + display_job $build $config $filename [expr $now-$time] + } + } + if {$S(failed)>0} { + puts "Failures: " + mydb eval { + SELECT build, config, filename FROM script WHERE state='failed' + } { + display_job $build $config $filename + } + } + + mydb close + exit +} + +#------------------------------------------------------------------------- +# Parse the command line. +# +for {set ii 0} {$ii < [llength $argv]} {incr ii} { + set isLast [expr $ii==([llength $argv]-1)] + set a [lindex $argv $ii] + set n [string length $a] + + if {[string range $a 0 0]=="-"} { + if {($n>2 && [string match "$a*" --jobs]) || $a=="-j"} { + incr ii + set TRG(nJob) [lindex $argv $ii] + if {$isLast} { usage } + } else { + usage + } + } else { + lappend TRG(patternlist) [string map {% *} $a] + } +} +set argv [list] + + + +# This script runs individual tests - tcl scripts or [make xyz] commands - +# in directories named "testdir$N", where $N is an integer. This variable +# contains a list of integers indicating the directories in use. +# +# This variable is accessed only via the following commands: +# +# dirs_nHelper +# Return the number of entries currently in the list. +# +# dirs_freeDir IDIR +# Remove value IDIR from the list. It is an error if it is not present. +# +# dirs_allocDir +# Select a value that is not already in the list. Add it to the list +# and return it. +# +set TRG(dirs_in_use) [list] + +proc dirs_nHelper {} { + global TRG + llength $TRG(dirs_in_use) +} +proc dirs_freeDir {iDir} { + global TRG + set out [list] + foreach d $TRG(dirs_in_use) { + if {$iDir!=$d} { lappend out $d } + } + if {[llength $out]!=[llength $TRG(dirs_in_use)]-1} { + error "dirs_freeDir could not find $iDir" + } + set TRG(dirs_in_use) $out +} +proc dirs_allocDir {} { + global TRG + array set inuse [list] + foreach d $TRG(dirs_in_use) { + set inuse($d) 1 + } + for {set iRet 0} {[info exists inuse($iRet)]} {incr iRet} { } + lappend TRG(dirs_in_use) $iRet + return $iRet +} set testdir [file dirname $argv0] -# Parse the command line options. There are two ways to invoke this -# script - to create a helper or coordinator process. If there are -# no helper processes, the coordinator runs test scripts. +# Check that directory $dir exists. If it does not, create it. If +# it does, delete its contents. # -# To create a helper process: -# -# testrunner.tcl helper ID -# -# where ID is an integer greater than 0. The process will create and -# run tests in the "testdir$ID" directory. Helper processes are only -# created by coordinators - there is no need for a user to create -# helper processes manually. -# -# If the first argument is anything other than "helper", then a coordinator -# process is started. See the implementation of the [usage] proc above for -# details. -# -switch -- [lindex $argv 0] { - helper { - set R(helper) 1 - set R(helper_id) [lindex $argv 1] - set argv [list --testdir=testdir$R(helper_id)] - } - - default { - set R(helper) 0 - set R(helper_id) 0 - +proc create_or_clear_dir {dir} { + set dir [file normalize $dir] + catch { file mkdir $dir } + foreach f [glob -nocomplain [file join $dir *]] { + catch { file delete -force $f } } } -if {$R(helper)==0} { - for {set ii 0} {$ii < [llength $argv]} {incr ii} { - set a [lindex $argv $ii] - set n [string length $a] - if {[string range $a 0 0]=="-"} { - if {($n>2 && [string match "$a*" --jobs]) || $a=="-j"} { - incr ii - set R(nJob) [lindex $argv $ii] - } else { - usage - } - } else { - lappend R(patternlist) [string map {% *} $a] - } +proc copy_dir {from to} { + foreach f [glob -nocomplain [file join $from *]] { + catch { file copy -force $f $to } } - - set argv [list] } -source $testdir/permutations.test + +proc build_to_dirname {bname} { + set fold [string tolower [string map {- _} $bname]] + return "testrunner_build_$fold" +} #------------------------------------------------------------------------- # Return a list of tests to run. Each element of the list is itself a # list of two elements - the name of a permuations.test configuration # followed by the full path to a test script. i.e.: # -# {CONFIG FILENAME} {CONFIG FILENAME} ... +# {BUILD CONFIG FILENAME} {BUILD CONFIG FILENAME} ... # proc testset_patternlist {patternlist} { + set testset [list] ;# return value + set first [lindex $patternlist 0] - if {$first=="all"} { set first "full" } if {$first=="release"} { + set platform $::TRG(platform) - # The following mirrors the set of test suites invoked by "all.test". - # - set clist { - full - no_optimization memsubsys1 memsubsys2 singlethread - multithread onefile utf16 exclusive persistent_journal - persistent_journal_error no_journal no_journal_error - autovacuum_ioerr no_mutex_try fullmutex journaltest - inmemory_journal pcache0 pcache10 pcache50 pcache90 - pcache100 prepare mmap + set patternlist [lrange $patternlist 1 end] + foreach b [trd_builds $platform] { + foreach c [trd_configs $platform $b] { + testset_append testset $b $c $patternlist + } + + if {[llength $patternlist]==0 || $b=="User-Auth"} { + set target testfixture + } else { + set target coretestprogs + } + lappend testset [list $b build $target] } - ifcapable rbu { lappend clist rbu } - if {$::tcl_platform(platform)=="unix"} { - ifcapable !default_autovacuum { - lappend clist autovacuum_crash + + if {[llength $patternlist]==0} { + foreach b [trd_builds $platform] { + foreach e [trd_extras $platform $b] { + lappend testset [list $b make $e] + } } } + + } elseif {$first=="all"} { + + set clist [trd_all_configs] set patternlist [lrange $patternlist 1 end] + foreach c $clist { + testset_append testset "" $c $patternlist + } } elseif {[info exists ::testspec($first)]} { set clist $first set patternlist [lrange $patternlist 1 end] + + testset_append testset "" $first [lrange $patternlist 1 end] } elseif { [llength $patternlist]==0 } { - set clist veryquick + testset_append testset "" veryquick $patternlist } else { - set clist full + testset_append testset "" full $patternlist } - set testset [list] + set testset +} - foreach config $clist { - catch { array unset O } - array set O $::testspec($config) - foreach f $O(-files) { - if {[file pathtype $f]!="absolute"} { - set f [file join $::testdir $f] - } - lappend testset [list $config [file normalize $f]] - } - } +proc testset_append {listvar build config patternlist} { + upvar $listvar lvar - if {[llength $patternlist]>0} { - foreach t $testset { - set tail [file tail [lindex $t 1]] + catch { array unset O } + array set O $::testspec($config) + + foreach f $O(-files) { + if {[llength $patternlist]>0} { + set bMatch 0 foreach p $patternlist { - if {[string match $p $tail]} { - lappend ret $t - break; + if {[string match $p [file tail $f]]} { + set bMatch 1 + break } } + if {$bMatch==0} continue } - } else { - set ret $testset - } - set ret + if {[file pathtype $f]!="absolute"} { + set f [file join $::testdir $f] + } + lappend lvar [list $build $config $f] + } } + #-------------------------------------------------------------------------- proc r_write_db {tcl} { - global R - - sqlite3_test_control_pending_byte 0x010000 - sqlite3 db $R(dbname) - db timeout $R(timeout) - db eval { BEGIN EXCLUSIVE } - + trdb eval { BEGIN EXCLUSIVE } uplevel $tcl - - db eval { COMMIT } - db close + trdb eval { COMMIT } } -proc make_new_testset {} { - global R +# Obtain a new job to be run by worker $iJob (an integer). A job is +# returned as a three element list: +# +# {$build $config $file} +# +proc r_get_next_job {iJob} { + global T - set tests [testset_patternlist $R(patternlist)] - r_write_db { - db eval $R(schema) - foreach t $tests { - foreach {c s} $t {} - set slow 0 - - set fd [open $s] - for {set ii 0} {$ii<100 && ![eof $fd]} {incr ii} { - set line [gets $fd] - if {[string match -nocase *testrunner:* $line]} { - regexp -nocase {.*testrunner:(.*)} $line -> properties - foreach p $properties { - if {$p=="slow"} { set slow 1 } - } - } - } - close $fd - - db eval { - INSERT INTO script(config, filename, slow, state) - VALUES ($c, $s, $slow, 'ready') - } - } + if {($iJob%2)} { + set orderby "ORDER BY priority ASC" + } else { + set orderby "ORDER BY priority DESC" } -} - -# Find the next job in the database and mark it as 'running'. Then return -# a list consisting of the -# -# CONFIG FILENAME -# -# pair for the test. -# -proc get_next_test {} { - global R - set myid $R(helper_id) r_write_db { set f "" set c "" - db eval { - SELECT config, filename FROM script WHERE state='ready' - ORDER BY - (slow * (($myid+1) % 2)) DESC, - config!='full', - config, - filename - LIMIT 1 - } { + trdb eval " + SELECT build, config, filename + FROM script + WHERE state='ready' + $orderby LIMIT 1 + " { + set b $build set c $config set f $filename } if {$f!=""} { - db eval { - UPDATE script SET state='running', testfixtureid=$myid - WHERE (config, filename) = ($c, $f) + set tm [clock_milliseconds] + set T($iJob) $tm + trdb eval { + UPDATE script SET state='running', time=$tm + WHERE (build, config, filename) = ($b, $c, $f) } } } if {$f==""} { return "" } - list $c $f + list $b $c $f } -proc r_testname {config filename} { - set name [file tail $filename] - if {$config!="" && $config!="full" && $config!="veryquick"} { - set name "$config-$name" - } - return $name -} +#rename r_get_next_job r_get_next_job_r +#proc r_get_next_job {iJob} { +# puts [time { set res [r_get_next_job_r $iJob] }] +# set res +#} -proc r_set_test_result {config filename ms nerr ntest output} { - global R - - set f [r_testname $config $filename] - if {$nerr==0} { - set msg "$f... Ok" - } else { - set msg "$f... FAILED - $nerr errors of $ntest tests" - } - append msg " (${ms}ms)" - if {$R(helper)} { - append msg " (helper $R(helper_id))" - } - - sqlite3_shutdown - set nMalloc [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] - set nByte [sqlite3_memory_used] - if {($nByte>0 || $nMalloc>0) && $R(leaker)==""} { - set R(leaker) $f - } +proc make_new_testset {} { + global TRG + set tests [testset_patternlist $TRG(patternlist)] r_write_db { - db eval { - UPDATE script - SET state='done', output=$output, nerr=$nerr, ntest=$ntest, time=$ms - WHERE (config, filename)=($config, $filename); - INSERT INTO msg(msg) VALUES ($msg); + trdb eval $TRG(schema) + set nJob $TRG(nJob) + set cmdline $TRG(cmdline) + set tm [clock_milliseconds] + trdb eval { REPLACE INTO config VALUES('njob', $nJob ); } + trdb eval { REPLACE INTO config VALUES('cmdline', $cmdline ); } + trdb eval { REPLACE INTO config VALUES('start', $tm ); } + + foreach t $tests { + foreach {b c s} $t {} + set slow 0 + + if {$c!="make" && $c!="build"} { + set fd [open $s] + for {set ii 0} {$ii<100 && ![eof $fd]} {incr ii} { + set line [gets $fd] + if {[string match -nocase *testrunner:* $line]} { + regexp -nocase {.*testrunner:(.*)} $line -> properties + foreach p $properties { + if {$p=="slow"} { set slow 1 } + if {$p=="superslow"} { set slow 2 } + } + } + } + close $fd + } + + if {$c=="veryquick"} { + set c "" + } + + set state ready + if {$b!="" && $c!="build"} { + set state "" + } + + trdb eval { + INSERT INTO script(build, config, filename, slow, state) + VALUES ($b, $c, $s, $slow, $state) + } } } } -set R(iNextMsg) 1 -proc r_get_messages {{db ""}} { - global R +proc script_input_ready {fd iJob b c f} { + global TRG + global O + global T - sqlite3_test_control_pending_byte 0x010000 + if {[eof $fd]} { + set ::done 1 + fconfigure $fd -blocking 1 + set state "done" + set rc [catch { close $fd } msg] + if {$rc} { + puts "FAILED: $b $c $f" + set state "failed" + } - if {$db==""} { - sqlite3 rgmhandle $R(dbname) - set dbhandle rgmhandle - $dbhandle timeout $R(timeout) + set tm [expr [clock_milliseconds] - $T($iJob)] + + puts $TRG(log) "### $b ### $c ### $f ${tm}ms ($state)" + puts $TRG(log) [string trim $O($iJob)] + + r_write_db { + set output $O($iJob) + trdb eval { + UPDATE script SET output = $output, state=$state, time=$tm + WHERE (build, config, filename) = ($b, $c, $f) + } + if {$state=="done" && $c=="build"} { + trdb eval { + UPDATE script SET state = 'ready' WHERE (build, state)==($b, '') + } + } + } + + dirs_freeDir $iJob + launch_some_jobs + incr ::wakeup } else { - set dbhandle $db - } - - $dbhandle transaction { - set next $R(iNextMsg) - set ret [$dbhandle eval {SELECT msg FROM msg WHERE id>=$next}] - set R(iNextMsg) [$dbhandle one {SELECT COALESCE(max(id), 0)+1 FROM msg}] - } - - if {$db==""} { - rgmhandle close - } - - set ret -} - -# This is called after all tests have been run to write the leaked memory -# report into the malloc table of testrunner.db. -# -proc r_memory_report {} { - global R - - sqlite3_shutdown - - set nMalloc [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] - set nByte [sqlite3_memory_used] - set id $R(helper_id) - set leaker $R(leaker) - - r_write_db { - db eval { - INSERT INTO malloc(id, nMalloc, nByte, leaker) - VALUES($id, $nMalloc, $nByte, $leaker) + set rc [catch { gets $fd line } res] + if {$rc} { + puts "ERROR $res" + } + if {$res>=0} { + append O($iJob) "$line\n" } } + } - -#-------------------------------------------------------------------------- -# -set ::R_INSTALL_PUTS_WRAPPER { - proc puts_sts_wrapper {args} { - set n [llength $args] - if {$n==1 || ($n==2 && [string first [lindex $args 0] -nonewline]==0)} { - uplevel puts_into_caller $args - } else { - # A channel was explicitly specified. - uplevel puts_sts_original $args - } - } - rename puts puts_sts_original - proc puts {args} { uplevel puts_sts_wrapper $args } +proc dirname {ii} { + return "testdir$ii" } -proc r_install_puts_wrapper {} $::R_INSTALL_PUTS_WRAPPER -proc r_uninstall_puts_wrapper {} { - rename puts "" - rename puts_sts_original puts -} +proc launch_another_job {iJob} { + global TRG + global O + global T -proc slave_test_script {script} { + set testfixture [info nameofexec] + set script $TRG(info_script) - # Create the interpreter used to run the test script. - interp create tinterp + set dir [dirname $iJob] + create_or_clear_dir $dir - # Populate some global variables that tester.tcl expects to see. - foreach {var value} [list \ - ::argv0 $::argv0 \ - ::argv {} \ - ::SLAVE 1 \ - ] { - interp eval tinterp [list set $var $value] - } - - # The alias used to access the global test counters. - tinterp alias set_test_counter set_test_counter - - # Set up an empty ::cmdlinearg array in the slave. - interp eval tinterp [list array set ::cmdlinearg [array get ::cmdlinearg]] - - # Set up the ::G array in the slave. - interp eval tinterp [list array set ::G [array get ::G]] - interp eval tinterp [list set ::G(runner.tcl) 1] - - interp eval tinterp $::R_INSTALL_PUTS_WRAPPER - tinterp alias puts_into_caller puts_into_caller - - # Load the various test interfaces implemented in C. - load_testfixture_extensions tinterp - - # Run the test script. - set rc [catch { interp eval tinterp $script } msg opt] - if {$rc} { - puts_into_caller $msg - puts_into_caller [dict get $opt -errorinfo] - incr ::TC(errors) - } - - # Check if the interpreter call [run_thread_tests] - if { [interp eval tinterp {info exists ::run_thread_tests_called}] } { - set ::run_thread_tests_called 1 - } - - # Delete the interpreter used to run the test script. - interp delete tinterp -} - -proc slave_test_file {zFile} { - set tail [file tail $zFile] - - # Remember the value of the shared-cache setting. So that it is possible - # to check afterwards that it was not modified by the test script. - # - ifcapable shared_cache { set scs [sqlite3_enable_shared_cache] } - - # Run the test script in a slave interpreter. - # - unset -nocomplain ::run_thread_tests_called - reset_prng_state - set ::sqlite_open_file_count 0 - set time [time { slave_test_script [list source $zFile] }] - set ms [expr [lindex $time 0] / 1000] - - r_install_puts_wrapper - - # Test that all files opened by the test script were closed. Omit this - # if the test script has "thread" in its name. The open file counter - # is not thread-safe. - # - if {[info exists ::run_thread_tests_called]==0} { - do_test ${tail}-closeallfiles { expr {$::sqlite_open_file_count>0} } {0} - } - set ::sqlite_open_file_count 0 - - # Test that the global "shared-cache" setting was not altered by - # the test script. - # - ifcapable shared_cache { - set res [expr {[sqlite3_enable_shared_cache] == $scs}] - do_test ${tail}-sharedcachesetting [list set {} $res] 1 - } - - # Add some info to the output. - # - output2 "Time: $tail $ms ms" - show_memstats - - r_uninstall_puts_wrapper - return $ms -} - -proc puts_into_caller {args} { - global R - if {[llength $args]==1} { - append R(output) [lindex $args 0] - append R(output) "\n" - } else { - append R(output) [lindex $args 1] - } -} - -#------------------------------------------------------------------------- -# -proc r_final_report {} { - global R - - sqlite3_test_control_pending_byte 0x010000 - sqlite3 db $R(dbname) - - db timeout $R(timeout) - - set errcode 0 - - # Create the text log file. This is just the concatenation of the - # 'output' column of the database for every script that was run. - set fd [open $R(logname) w] - db eval {SELECT output FROM script ORDER BY config!='full',config,filename} { - puts $fd $output - } - close $fd - - # Check if any scripts reported errors. If so, print one line noting - # how many errors, and another identifying the scripts in which they - # occured. Or, if no errors occurred, print out "no errors at all!". - sqlite3 db $R(dbname) - db timeout $R(timeout) - db eval { SELECT sum(nerr) AS nerr, sum(ntest) AS ntest FROM script } { } - puts "$nerr errors from $ntest tests." - if {$nerr>0} { - db eval { SELECT config, filename FROM script WHERE nerr>0 } { - lappend errlist [r_testname $config $filename] - } - puts "Errors in: $errlist" - set errcode 1 - } - - # Check if any scripts were not run or did not finish. Print out a - # line identifying them if there are any. - set errlist [list] - db eval { SELECT config, filename FROM script WHERE state!='done' } { - lappend errlist [r_testname $config $filename] - } - if {$errlist!=[list]} { - puts "Tests DID NOT FINISH (crashed?): $errlist" - set errcode 1 - } - - set bLeak 0 - db eval { - SELECT id, nmalloc, nbyte, leaker FROM malloc - WHERE nmalloc>0 OR nbyte>0 - } { - if {$id==0} { - set line "This process " - } else { - set line "Helper $id " - } - append line "leaked $nbyte byte in $nmalloc allocations" - if {$leaker!=""} { append line " (perhaps in [file tail $leaker])" } - puts $line - set bLeak 1 - } - if {$bLeak==0} { - puts "No leaks - all allocations freed." - } - - db close - - puts "Test database is $R(dbname)" - puts "Test log file is $R(logname)" - if {$errcode} { - puts "This test has FAILED." - } - return $errcode -} - - -if {$R(helper)==0} { - make_new_testset -} - -set R(nHelperRunning) 0 -if {$R(helper)==0 && $R(nJob)>1} { - cd $cmdlinearg(TESTFIXTURE_HOME) - for {set ii 1} {$ii <= $R(nJob)} {incr ii} { - set cmd "[info nameofexec] $R(info_script) helper $ii 2>@1" - puts "Launching helper $ii ($cmd)" - set chan [open "|$cmd" r] - fconfigure $chan -blocking false - fileevent $chan readable [list r_helper_readable $ii $chan] - incr R(nHelperRunning) - } - cd $cmdlinearg(testdir) -} - -proc r_helper_readable {id chan} { - set data [gets $chan] - if {$data!=""} { puts "helper $id:$data" } - if {[eof $chan]} { - puts "helper $id is finished" - incr ::R(nHelperRunning) -1 - close $chan - } -} - -if {$R(nHelperRunning)==0} { - while { ""!=[set t [get_next_test]] } { - set R(output) "" - set TC(count) 0 - set TC(errors) 0 - - foreach {config filename} $t {} - - array set O $::testspec($config) - set ::G(perm:name) $config - set ::G(perm:prefix) $O(-prefix) - set ::G(isquick) 1 - set ::G(perm:dbconfig) $O(-dbconfig) - set ::G(perm:presql) $O(-presql) - - eval $O(-initialize) - set ms [slave_test_file $filename] - eval $O(-shutdown) - - unset -nocomplain ::G(perm:sqlite3_args) - unset ::G(perm:name) - unset ::G(perm:prefix) - unset ::G(perm:dbconfig) - unset ::G(perm:presql) - - r_set_test_result $config $filename $ms $TC(errors) $TC(count) $R(output) + set O($iJob) "" - if {$R(helper)==0} { - foreach msg [r_get_messages] { puts $msg } + set job [r_get_next_job $iJob] + if {$job==""} { return 0 } + + foreach {b c f} $job {} + + if {$c=="build"} { + set testdir [file dirname $TRG(info_script)] + set srcdir [file dirname $testdir] + set builddir [build_to_dirname $b] + create_or_clear_dir $builddir + + set cmd [info nameofexec] + lappend cmd [file join $testdir releasetest_data.tcl] + lappend cmd trscript + if {$TRG(platform)=="win"} { lappend cmd -msvc } + lappend cmd $b $srcdir + + set script [exec {*}$cmd] + set fd [open [file join $builddir $TRG(make)] w] + puts $fd $script + close $fd + + puts "Launching build \"$b\" in directory $builddir..." + set target coretestprogs + if {$b=="User-Auth"} { set target testfixture } + + set cmd "$TRG(makecmd) $target" + set dir $builddir + + } elseif {$c=="make"} { + set builddir [build_to_dirname $b] + copy_dir $builddir $dir + set cmd "$TRG(makecmd) $f" + } else { + if {$b==""} { + set testfixture [info nameofexec] + } else { + set tail testfixture + if {$TRG(platform)=="win"} { set tail testfixture.exe } + set testfixture [file normalize [file join [build_to_dirname $b] $tail]] + } + + if {$c=="valgrind"} { + set testfixture "valgrind -v --error-exitcode=1 $testfixture" + set ::env(OMIT_MISUSE) 1 + } + set cmd [concat $testfixture [list $script $c $f]] + } + + set pwd [pwd] + cd $dir + set fd [open "|$cmd 2>@1" r] + cd $pwd + set pid [pid $fd] + + fconfigure $fd -blocking false + fileevent $fd readable [list script_input_ready $fd $iJob $b $c $f] + unset -nocomplain ::env(OMIT_MISUSE) + + return 1 +} + +proc one_line_report {} { + global TRG + + set tm [expr [clock_milliseconds] - $TRG(starttime)] + set tm [format "%.2f" [expr $tm/1000.0]] + + foreach s {ready running done failed} { + set v($s,build) 0 + set v($s,make) 0 + set v($s,script) 0 + } + + r_write_db { + trdb eval { + SELECT state, jobtype, count(*) AS cnt + FROM script + GROUP BY state, jobtype + } { + set v($state,$jobtype) $cnt + if {[info exists t($jobtype)]} { + incr t($jobtype) $cnt + } else { + set t($jobtype) $cnt + } } } - # Tests are finished - write a record into testrunner.db describing - # any memory leaks. - r_memory_report - -} else { - set TTT 0 - sqlite3 db $R(dbname) - db timeout $R(timeout) - while {$R(nHelperRunning)>0} { - after 250 { incr TTT } - vwait TTT - foreach msg [r_get_messages db] { puts $msg } + set text "" + foreach j [array names t] { + set fin [expr $v(done,$j) + $v(failed,$j)] + lappend text "$j: ($fin/$t($j)) f=$v(failed,$j) r=$v(running,$j)" } - db close + + puts "${tm}s: [join $text { || }]" + after $TRG(reporttime) one_line_report } -set errcode 0 -if {$R(helper)==0} { - set errcode [r_final_report] +proc launch_some_jobs {} { + global TRG + r_write_db { + set nJob [trdb one { SELECT value FROM config WHERE name='njob' }] + } + while {[dirs_nHelper]<$nJob} { + set iDir [dirs_allocDir] + if {0==[launch_another_job $iDir]} { + dirs_freeDir $iDir + break; + } + } } -exit $errcode +proc run_testset {} { + global TRG + set ii 0 + + set TRG(starttime) [clock_milliseconds] + set TRG(log) [open $TRG(logname) w] + + launch_some_jobs + # launch_another_job $ii + + one_line_report + while {[dirs_nHelper]>0} { + after 500 {incr ::wakeup} + vwait ::wakeup + } + close $TRG(log) + one_line_report + + r_write_db { + set nErr [trdb one {SELECT count(*) FROM script WHERE state='failed'}] + if {$nErr>0} { + puts "$nErr failures:" + trdb eval { + SELECT build, config, filename FROM script WHERE state='failed' + } { + puts "FAILED: $build $config $filename" + } + } + } + + puts "Test database is $TRG(dbname)" + puts "Test log is $TRG(logname)" +} + + +sqlite3 trdb $TRG(dbname) +trdb timeout $TRG(timeout) +set tm [lindex [time { make_new_testset }] 0] +puts "built testset in [expr $tm/1000]ms.." +run_testset +trdb close +#puts [pwd] diff --git a/test/testrunner_data.tcl b/test/testrunner_data.tcl new file mode 100644 index 0000000000..f74ee146ca --- /dev/null +++ b/test/testrunner_data.tcl @@ -0,0 +1,143 @@ + + + +namespace eval trd { + variable tcltest + variable extra + variable all_configs + + + # Tcl tests to run for various builds. + # + set tcltest(linux.Fast-One) veryquick + set tcltest(linux.Debug-One) veryquick + set tcltest(linux.Debug-Two) veryquick + set tcltest(linux.Have-Not) veryquick + set tcltest(linux.Secure-Delete) veryquick + set tcltest(linux.Unlock-Notify) veryquick + set tcltest(linux.User-Auth) veryquick + set tcltest(linux.Update-Delete-Limit) veryquick + set tcltest(linux.Extra-Robustness) veryquick + set tcltest(linux.Device-Two) veryquick + set tcltest(linux.No-lookaside) veryquick + set tcltest(linux.Devkit) veryquick + set tcltest(linux.Apple) veryquick + set tcltest(linux.Sanitize) veryquick + set tcltest(linux.Device-One) all + set tcltest(linux.Default) all_plus_autovacuum_crash + set tcltest(linux.Valgrind) valgrind + + set tcltest(osx.Locking-Style) veryquick + set tcltest(osx.Have-Not) veryquick + set tcltest(osx.Apple) all + + set tcltest(win.Stdcall) veryquick + set tcltest(win.Have-Not) veryquick + set tcltest(win.Windows-Memdebug) veryquick + set tcltest(win.Windows-Win32Heap) veryquick + set tcltest(win.Default) full + + # Extra [make xyz] tests that should be run for various builds. + # + set extra(linux.Check-Symbols) checksymbols + set extra(linux.Fast-One) {fuzztest sourcetest} + set extra(linux.Debug-One) {fuzztest sourcetest mptest} + set extra(linux.Debug-Two) {fuzztest sourcetest} + set extra(linux.Have-Not) {fuzztest sourcetest} + set extra(linux.Secure-Delete) {fuzztest sourcetest} + set extra(linux.Unlock-Notify) {fuzztest sourcetest} + set extra(linux.Update-Delete-Limit) {fuzztest sourcetest} + set extra(linux.Extra-Robustness) {fuzztest sourcetest} + set extra(linux.Device-Two) {fuzztest sourcetest threadtest} + set extra(linux.No-lookaside) {fuzztest sourcetest} + set extra(linux.Devkit) {fuzztest sourcetest} + set extra(linux.Apple) {fuzztest sourcetest} + set extra(linux.Sanitize) {fuzztest sourcetest} + set extra(linux.Default) {fuzztest sourcetest threadtest} + + set extra(osx.Apple) {fuzztest threadtest} + set extra(osx.Have-Not) {fuzztest sourcetest} + set extra(osx.Locking-Style) {mptest fuzztest sourcetest} + + set extra(win.Default) mptest + set extra(win.Stdcall) {fuzztest sourcetest} + set extra(win.Windows-Memdebug) {fuzztest sourcetest} + set extra(win.Windows-Win32Heap) {fuzztest sourcetest} + set extra(win.Have-Not) {fuzztest sourcetest} + + # The following mirrors the set of test suites invoked by "all.test". + # + set all_configs { + full no_optimization memsubsys1 memsubsys2 singlethread + multithread onefile utf16 exclusive persistent_journal + persistent_journal_error no_journal no_journal_error + autovacuum_ioerr no_mutex_try fullmutex journaltest + inmemory_journal pcache0 pcache10 pcache50 pcache90 + pcache100 prepare mmap + } +} + + +#------------------------------------------------------------------------- +proc trd_import {} { + uplevel { + variable ::trd::tcltest + variable ::trd::extra + variable ::trd::all_configs + } +} + +proc trd_builds {platform} { + trd_import + + set klist [lsort -uniq [concat \ + [array names tcltest ${platform}.*] \ + [array names extra ${platform}.*] \ + ]] + if {[llength $klist]==0} { + error "no such platform: $platform" + } + + set ret "" + foreach k $klist { + foreach {p c} [split $k "."] {} + lappend ret $c + } + set ret +} + +proc trd_configs {platform build} { + trd_import + + set clist [list] + + if {[info exists tcltest($platform.$build)]} { + set clist $tcltest($platform.$build) + if {$clist=="all"} { + set clist $all_configs + } elseif {$clist=="all_plus_autovacuum_crash"} { + set clist [concat $all_configs autovacuum_crash] + } + } + + set clist +} + +proc trd_extras {platform build} { + trd_import + + set elist [list] + if {[info exists extra($platform.$build)]} { + set elist $extra($platform.$build) + } + + set elist +} + +proc trd_all_configs {} { + trd_import + set all_configs +} + + + diff --git a/test/vt02.c b/test/vt02.c index 40bd6fcb3e..f83fc9af95 100644 --- a/test/vt02.c +++ b/test/vt02.c @@ -177,6 +177,8 @@ #include #endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Forward declarations */ typedef struct vt02_vtab vt02_vtab; typedef struct vt02_cur vt02_cur; @@ -999,6 +1001,10 @@ static void vt02CoreInit(sqlite3 *db){ sqlite3_create_module(db, "vt02pkabcd", &vt02Module, (void*)zPkABCDSchema); } +#else +# define vt02CoreInit(db) +#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ + #ifdef TH3_VERSION static void vt02_init(th3state *p, int iDb, char *zArg){ vt02CoreInit(th3dbPointer(p, iDb)); diff --git a/test/windowB.test b/test/windowB.test index 2548165956..1c7234ce42 100644 --- a/test/windowB.test +++ b/test/windowB.test @@ -411,6 +411,7 @@ do_execsql_test 10.3 { } ifcapable json1 { +if {[permutation]!="no_optimization"} { do_execsql_test 11.0 { SELECT value FROM json_each('[1,2,3,4,5]'); @@ -479,7 +480,7 @@ ifcapable json1 { | `--USE TEMP B-TREE FOR ORDER BY `--SCAN (subquery-xxxxxx) } -} +}} finish_test