Index: test/crash8.test ================================================================== --- test/crash8.test +++ test/crash8.test @@ -380,11 +380,11 @@ INSERT INTO t1 SELECT randomblob(900) FROM t1; INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 64 rows */ BEGIN; UPDATE t1 SET x = randomblob(900); } - file delete -force testX.db testX.db-journal + file delete -force testX.db testX.db-journal testX.db-wal copy_file test.db testX.db copy_file test.db-journal testX.db-journal db close crashsql -file test.db -delay [expr ($::i%2) + 1] { Index: test/lock_common.tcl ================================================================== --- test/lock_common.tcl +++ test/lock_common.tcl @@ -10,10 +10,56 @@ #*********************************************************************** # This file contains code used by several different test scripts. The # code in this file allows testfixture to control another process (or # processes) to test locking. # + +proc do_multiclient_test {varname script} { + + 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 } + + uplevel set $varname $tn + uplevel $script + + code2 { db2 close } + code3 { db3 close } + catch { close $::code2_chan } + catch { close $::code3_chan } + } +} # Launch another testfixture process to be controlled by this one. A # channel name is returned that may be passed as the first argument to proc # 'testfixture' to execute a command. The child testfixture process is shut # down by closing the channel. Index: test/pager1.test ================================================================== --- test/pager1.test +++ test/pager1.test @@ -13,44 +13,11 @@ 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 } +do_multiclient_test tn { # 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 { @@ -74,11 +41,10 @@ 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. # @@ -181,14 +147,9 @@ 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 Index: test/wal.test ================================================================== --- test/wal.test +++ test/wal.test @@ -14,10 +14,11 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl +source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } proc reopen_db {} { catch { db close } @@ -457,49 +458,22 @@ # The following block of tests - wal-10.* - test that the WAL locking # scheme works in simple cases. This block of tests is run twice. Once # using multiple connections in the address space of the current process, # and once with all connections except one running in external processes. # -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 -}] { - - eval $code - reopen_db - - # 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. - # - code2 { sqlite3 db2 test.db ; db2 eval { PRAGMA journal_mode = WAL } } - code3 { sqlite3 db3 test.db ; db3 eval { PRAGMA journal_mode = WAL } } - - # Shorthand commands. Execute SQL using database connection [db2] or - # [db3]. Return the results. - # - proc sql2 {sql} { code2 [list db2 eval $sql] } - proc sql3 {sql} { code3 [list db3 eval $sql] } +do_multiclient_test tn { # Initialize the database schema and contents. # do_test wal-10.$tn.1 { execsql { + PRAGMA journal_mode = wal; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); SELECT * FROM t1; } - } {1 2} + } {wal 1 2} # Open a transaction and write to the database using [db]. Check that [db2] # is still able to read the snapshot before the transaction was opened. # do_test wal-10.$tn.2 { @@ -690,16 +664,10 @@ } {a b c d} do_test wal-10.$tn.37 { sql2 COMMIT execsql { PRAGMA wal_checkpoint } } {} - - catch { db close } - catch { code2 { db2 close } } - catch { code3 { db3 close } } - catch { close $::code2_chan } - catch { close $::code3_chan } } #------------------------------------------------------------------------- # This block of tests, wal-11.*, test that nothing goes terribly wrong # if frames must be written to the log file before a transaction is @@ -898,51 +866,37 @@ } [expr int(pow(2, 16))] do_test wal-13.2.3 { expr [file size test.db-wal] > [log_file_size 33000 1024] } 1 -foreach code [list { - set tn 3 - proc buddy {tcl} { uplevel #0 $tcl } -} { - set tn 4 - set ::buddy [launch_testfixture] - proc buddy {tcl} { testfixture $::buddy $tcl } -}] { - - eval $code - reopen_db +do_multiclient_test tn { + incr tn 2 do_test wal-13.$tn.0 { - buddy { sqlite3 db2 test.db } - execsql { + sql1 { PRAGMA journal_mode = WAL; CREATE TABLE t1(x); INSERT INTO t1 SELECT randomblob(800); } - execsql { SELECT count(*) FROM t1 } + sql1 { SELECT count(*) FROM t1 } } {1} for {set ii 1} {$ii<16} {incr ii} { do_test wal-13.$tn.$ii.a { - buddy { db2 eval { INSERT INTO t1 SELECT randomblob(800) FROM t1 } } - buddy { db2 eval { SELECT count(*) FROM t1 } } + sql2 { INSERT INTO t1 SELECT randomblob(800) FROM t1 } + sql2 { SELECT count(*) FROM t1 } } [expr (1<<$ii)] do_test wal-13.$tn.$ii.b { - db eval { SELECT count(*) FROM t1 } + sql1 { SELECT count(*) FROM t1 } } [expr (1<<$ii)] do_test wal-13.$tn.$ii.c { - db eval { SELECT count(*) FROM t1 } + sql1 { SELECT count(*) FROM t1 } } [expr (1<<$ii)] do_test wal-13.$tn.$ii.d { - db eval { PRAGMA integrity_check } + sql1 { PRAGMA integrity_check } } {ok} } - - catch { db2 close } - catch { close $::buddy } - db close } #------------------------------------------------------------------------- # Check a fun corruption case has been fixed. # Index: test/wal3.test ================================================================== --- test/wal3.test +++ test/wal3.test @@ -108,49 +108,23 @@ execsql { PRAGMA integrity_check } db2 } {ok} db2 close } -db close -foreach code [list { - proc code2 {tcl} { uplevel #0 $tcl } - proc code3 {tcl} { uplevel #0 $tcl } - set tn singleproc -} { - 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 multiproc -}] { - file delete -force test.db test.db-wal test.db-journal - sqlite3 db test.db - eval $code - - # 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. - # - code2 { sqlite3 db2 test.db ; db2 eval { PRAGMA journal_mode = WAL } } - code3 { sqlite3 db3 test.db ; db3 eval { PRAGMA journal_mode = WAL } } - - # Shorthand commands. Execute SQL using database connection [db], [db2] - # or [db3]. Return the results. - # - proc sql {sql} { db eval $sql } - proc sql2 {sql} { code2 [list db2 eval $sql] } - proc sql3 {sql} { code3 [list db3 eval $sql] } +do_multiclient_test i { + + set testname(1) multiproc + set testname(2) singleproc + set tn $testname($i) do_test wal3-2.$tn.1 { - sql { + sql1 { PRAGMA page_size = 1024; PRAGMA auto_vacuum = OFF; PRAGMA journal_mode = WAL; } - sql { + sql1 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 'one'); BEGIN; SELECT * FROM t1; } @@ -179,11 +153,11 @@ # After [db2] has committed, a checkpoint can copy the entire log to the # database file. Checkpointing after [db3] has committed is therefore a # no-op, as the entire log has already been backfilled. # do_test wal3-2.$tn.4 { - sql { + sql1 { COMMIT; PRAGMA wal_checkpoint; } file size test.db } [expr $AUTOVACUUM ? 4*1024 : 3*1024] @@ -199,16 +173,10 @@ COMMIT; PRAGMA wal_checkpoint; } file size test.db } [expr $AUTOVACUUM ? 5*1024 : 4*1024] - - catch { db close } - catch { code2 { db2 close } } - catch { code3 { db3 close } } - catch { close $::code2_chan } - catch { close $::code3_chan } } catch {db close} #------------------------------------------------------------------------- # Test that that for the simple test: