diff --git a/manifest b/manifest index 9c7a7211b7..9124776a9a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Run\sextra\siterations\sin\swal3.test\sto\sensure\stest\scoverage. -D 2010-06-15T14:21:17 +C Add\stest\sfile\spager1.test,\scontaining\stests\sof\sinter-process\slocking\sin\snon-wal\smode. +D 2010-06-15T17:44:48 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -484,7 +484,7 @@ F test/lock4.test f4f36271aa5ae1da449646bf43c7341f6b2b4c4e F test/lock5.test 6b1f78f09ad1522843dad571b76b321e6f439bf7 F test/lock6.test 8df56060f396151777390982422c800d026e1722 F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64 -F test/lock_common.tcl 69d6b67f2ba63968ec2173bcd7310c5c7eca00a2 +F test/lock_common.tcl c03802ef77c3864f1a7d812b0760b59563f2613b F test/lookaside.test 1dd350dc6dff015c47c07fcc5a727a72fc5bae02 F test/main.test 2be2352ac77ac5b238c6337a5469aeeef57677e6 F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9 @@ -533,17 +533,18 @@ F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347 F test/null.test a8b09b8ed87852742343b33441a9240022108993 F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec +F test/pager1.test dcc50ea9c4fc8d6d7101733644655c8395826e9b F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb F test/pcache.test eebc4420b37cb07733ae9b6e99c9da7c40dd6d58 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16 -F test/permutations.test 28f46dfcc880e15ec7ab1ff36d12af765a0e3bc4 +F test/permutations.test 403099a8e191b43e5df19b8199b80178b3ece1d6 F test/pragma.test 6960f9efbce476f70ba9ee2171daf5042f9e3d8a F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc -F test/quick.test d2a697cf6d6db2725649670859365ef601289f96 +F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test 1084050991e9ba22c1c10edd8d84673b501cc25a @@ -820,7 +821,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 03c0f4fd9cbb655477b63ebbb6af7822715644aa -R a2075e9740cf75b8937129b9cbcda629 +P ea80cbe51e33d6a3f15a4ad56f360fc5323866de +R 2d037491154b033cfc4dcca7e9e50afd U dan -Z 73996e320eea715ffc64316616623fba +Z 2d173a77ac2cf0416b30cd54aeed8e9e diff --git a/manifest.uuid b/manifest.uuid index 7b71e38dc6..8f08b18d48 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea80cbe51e33d6a3f15a4ad56f360fc5323866de \ No newline at end of file +6e43eed9310bae9ca5e91f8fd9eafc45a16b7019 \ No newline at end of file diff --git a/test/lock_common.tcl b/test/lock_common.tcl index 0683bbd389..83d20d6340 100644 --- a/test/lock_common.tcl +++ b/test/lock_common.tcl @@ -30,6 +30,7 @@ proc launch_testfixture {} { # Execute a command in a child testfixture process, connected by two-way # channel $chan. Return the result of the command, or an error message. +# proc testfixture {chan cmd} { puts $chan $cmd puts $chan OVER @@ -37,7 +38,9 @@ proc testfixture {chan cmd} { while { 1 } { set line [gets $chan] if { $line == "OVER" } { - return $r + set res [lindex $r 1] + if { [lindex $r 0] } { error $res } + return $res } if {[eof $chan]} { return "ERROR: Child process hung up" @@ -55,7 +58,7 @@ proc testfixture_nb_cb {varname chan} { } if { $line == "OVER" } { - set $varname $::tfnb($chan) + set $varname [lindex $::tfnb($chan) 1] unset ::tfnb($chan) close $chan } else { @@ -89,8 +92,8 @@ puts $f { puts $l "READ $line" if { $line == "OVER" } { set rc [catch {eval $script} result] - puts $result - puts $l "WRITE $result" + puts [list $rc $result] + puts $l "WRITE [list $rc $result]" puts OVER puts $l "WRITE OVER" flush stdout diff --git a/test/pager1.test b/test/pager1.test new file mode 100644 index 0000000000..26ae518927 --- /dev/null +++ b/test/pager1.test @@ -0,0 +1,194 @@ +# 2010 June 15 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/lock_common.tcl +source $testdir/malloc_common.tcl + +foreach code [list { + set ::code2_chan [launch_testfixture] + set ::code3_chan [launch_testfixture] + proc code2 {tcl} { testfixture $::code2_chan $tcl } + proc code3 {tcl} { testfixture $::code3_chan $tcl } + set tn 1 +} { + proc code2 {tcl} { uplevel #0 $tcl } + proc code3 {tcl} { uplevel #0 $tcl } + set tn 2 +}] { + + faultsim_delete_and_reopen + + # Open connections [db2] and [db3]. Depending on which iteration this + # is, the connections may be created in this interpreter, or in + # interpreters running in other OS processes. As such, the [db2] and [db3] + # commands should only be accessed within [code2] and [code3] blocks, + # respectively. + # + eval $code + code2 { sqlite3 db2 test.db } + code3 { sqlite3 db3 test.db } + + # Shorthand commands. Execute SQL using database connection [db2] or + # [db3]. Return the results. + # + proc sql1 {sql} { db eval $sql } + proc sql2 {sql} { code2 [list db2 eval $sql] } + proc sql3 {sql} { code3 [list db3 eval $sql] } + + proc csql1 {sql} { list [catch { sql1 $sql } msg] $msg } + proc csql2 {sql} { list [catch { sql2 $sql } msg] $msg } + proc csql3 {sql} { list [catch { sql3 $sql } msg] $msg } + + # Create and populate a database table using connection [db]. Check + # that connections [db2] and [db3] can see the schema and content. + # + do_test pager1-$tn.1 { + sql1 { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE INDEX i1 ON t1(b); + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t1 VALUES(2, 'two'); + } + } {} + do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two} + do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two} + + # Open a transaction and add a row using [db]. This puts [db] in + # RESERVED state. Check that connections [db2] and [db3] can still + # read the database content as it was before the transaction was + # opened. [db] should see the inserted row. + # + do_test pager1-$tn.4 { + sql1 { + BEGIN; + INSERT INTO t1 VALUES(3, 'three'); + } + } {} + do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two} + do_test pager1-$tn.6 { sql3 { SELECT * FROM t1 } } {1 one 2 two} + do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} + + # [db] still has an open write transaction. Check that this prevents + # other connections (specifically [db2]) from writing to the database. + # + # Even if [db2] opens a transaction first, it may not write to the + # database. After the attempt to write the db within a transaction, + # [db2] is left with an open transaction, but not a read-lock on + # the main database. So it does not prevent [db] from committing. + # + do_test pager1-$tn.8 { + csql2 { UPDATE t1 SET a = a + 10 } + } {1 {database is locked}} + do_test pager1-$tn.9 { + csql2 { + BEGIN; + UPDATE t1 SET a = a + 10; + } + } {1 {database is locked}} + + # Have [db] commit its transactions. Check the other connections can + # now see the new database content. + # + do_test pager1-$tn.10 { sql1 { COMMIT } } {} + do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} + do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} + do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} + + # Check that, as noted above, [db2] really did keep an open transaction + # after the attempt to write the database failed. + # + do_test pager1-$tn.14 { + csql2 { BEGIN } + } {1 {cannot start a transaction within a transaction}} + do_test pager1-$tn.15 { sql2 { ROLLBACK } } {} + + # Have [db2] open a transaction and take a read-lock on the database. + # Check that this prevents [db] from writing to the database (outside + # of any transaction). After this fails, check that [db3] can read + # the db (showing that [db] did not take a PENDING lock etc.) + # + do_test pager1-$tn.15 { + sql2 { BEGIN; SELECT * FROM t1; } + } {1 one 2 two 3 three} + do_test pager1-$tn.16 { + csql1 { UPDATE t1 SET a = a + 10 } + } {1 {database is locked}} + do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} + + # This time, have [db] open a transaction before writing the database. + # This works - [db] gets a RESERVED lock which does not conflict with + # the SHARED lock [db2] is holding. + # + do_test pager1-$tn.18 { + sql1 { + BEGIN; + UPDATE t1 SET a = a + 10; + } + } {} + do_test pager1-$tn-19 { + sql1 { PRAGMA lock_status } + } {main reserved temp closed} + do_test pager1-$tn-20 { + sql2 { PRAGMA lock_status } + } {main shared temp closed} + + # Check that all connections can still read the database. Only [db] sees + # the updated content (as the transaction has not been committed yet). + # + do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} + do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} + do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} + + # Because [db2] still has the SHARED lock, [db] is unable to commit the + # transaction. If it tries, an error is returned and the connection + # upgrades to a PENDING lock. + # + # Once this happens, [db] can read the database and see the new content, + # [db2] (still holding SHARED) can still read the old content, but [db3] + # (not holding any lock) is prevented by [db]'s PENDING from reading + # the database. + # + do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}} + do_test pager1-$tn-25 { + sql1 { PRAGMA lock_status } + } {main pending temp closed} + do_test pager1-$tn.26 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} + do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} + do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} + + # Have [db2] commit its read transaction, releasing the SHARED lock it + # is holding. Now, neither [db2] nor [db3] may read the database (as [db] + # is still holding a PENDING). + # + do_test pager1-$tn.29 { sql2 { COMMIT } } {} + do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}} + do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} + + # [db] is now able to commit the transaction. Once the transaction is + # committed, all three connections can read the new content. + # + do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {} + do_test pager1-$tn.26 { sql1 { COMMIT } } {} + do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three} + do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three} + do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three} + + code2 { db2 close } + code3 { db3 close } + catch { close $::code2_chan } + catch { close $::code3_chan } +} + +finish_test + diff --git a/test/permutations.test b/test/permutations.test index 2ae739fbbc..10a18dad0b 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -9,7 +9,6 @@ # #*********************************************************************** # -# $Id: permutations.test,v 1.51 2009/07/01 18:09:02 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -48,6 +47,7 @@ proc test_suite {name args} { set ::testspec($name) [array get options] lappend ::testsuitelist $name + } #------------------------------------------------------------------------- @@ -120,6 +120,7 @@ set allquicktests [test_set $alltests -exclude { # full # veryquick_plus_notify2 # +lappend ::testsuitelist xxx test_suite "veryquick" -description { "Very" quick test suite. Runs in less than 5 minutes on a workstation. @@ -150,11 +151,11 @@ test_suite "full" -description { unset -nocomplain ::G(isquick) } +lappend ::testsuitelist xxx #------------------------------------------------------------------------- # Define the coverage related test suites: # # coverage-wal -# coverage-fkey # test_suite "coverage-wal" -description { Coverage tests for file wal.c. @@ -164,8 +165,14 @@ test_suite "coverage-wal" -description { walfault.test } +test_suite "coverage-pager" -description { + Coverage tests for file pager.c. +} -files { + pager1.test +} +lappend ::testsuitelist xxx #------------------------------------------------------------------------- # Define the permutation test suites: # @@ -803,13 +810,21 @@ proc run_test_suite {name} { } proc help {} { + puts "Usage: $::argv0 TESTSUITE ?TESTFILE?" + puts "" + puts "Available test-suites are:" foreach k $::testsuitelist { - array set o $::testspec($k) - puts "Test suite: \"$k\"" - set d [string trim $o(-description)] - set d [regsub {\n *} $d "\n "] - puts " $d" - puts "" + if {[info exists ::testspec($k)]==0} { + puts " ----------------------------------------" + puts "" + } else { + array set o $::testspec($k) + puts "Test suite: \"$k\"" + set d [string trim $o(-description)] + set d [regsub {\n *} $d "\n "] + puts " $d" + puts "" + } } exit -1 } diff --git a/test/quick.test b/test/quick.test index af9ee0cfb2..974b02de97 100644 --- a/test/quick.test +++ b/test/quick.test @@ -10,11 +10,6 @@ set testdir [file dirname $argv0] source $testdir/permutations.test -if {[info exists env(QUICKTEST_INCLUDE]} { - # A hack so that releasetest.tcl keeps working. - run_test_suite quick_plus_notify2 -} else { - run_test_suite quick -} +run_test_suite quick finish_test