diff options
Diffstat (limited to 'test/wal6.test')
-rw-r--r-- | test/wal6.test | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/test/wal6.test b/test/wal6.test new file mode 100644 index 0000000..9bbc584 --- /dev/null +++ b/test/wal6.test @@ -0,0 +1,269 @@ +# 2010 December 1 +# +# 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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this file is testing the operation of the library in +# "PRAGMA journal_mode=WAL" mode. +# + +set testdir [file dirname $argv0] +set testprefix wal6 +source $testdir/tester.tcl +source $testdir/lock_common.tcl +source $testdir/wal_common.tcl +source $testdir/malloc_common.tcl +ifcapable !wal {finish_test ; return } + +#------------------------------------------------------------------------- +# Changing to WAL mode in one connection forces the change in others. +# +db close +forcedelete test.db + +set all_journal_modes {delete persist truncate memory off} +foreach jmode $all_journal_modes { + + do_test wal6-1.0.$jmode { + sqlite3 db test.db + execsql "PRAGMA journal_mode = $jmode;" + } $jmode + + do_test wal6-1.1.$jmode { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + INSERT INTO t1 VALUES(1,2); + SELECT * FROM t1; + } + } {1 2} + +# Under Windows, you'll get an error trying to delete +# a file this is already opened. Close the first connection +# so the other tests work. +if {$tcl_platform(platform)=="windows"} { + if {$jmode=="persist" || $jmode=="truncate"} { + db close + } +} + + do_test wal6-1.2.$jmode { + sqlite3 db2 test.db + execsql { + PRAGMA journal_mode=WAL; + INSERT INTO t1 VALUES(3,4); + SELECT * FROM t1 ORDER BY a; + } db2 + } {wal 1 2 3 4} + +if {$tcl_platform(platform)=="windows"} { + if {$jmode=="persist" || $jmode=="truncate"} { + sqlite3 db test.db + } +} + + do_test wal6-1.3.$jmode { + execsql { + SELECT * FROM t1 ORDER BY a; + } + } {1 2 3 4} + + db close + db2 close + forcedelete test.db + +} + +#------------------------------------------------------------------------- +# Test that SQLITE_BUSY_SNAPSHOT is returned as expected. +# +reset_db +sqlite3 db2 test.db + +do_execsql_test 2.1 { + PRAGMA journal_mode = WAL; + CREATE TABLE t1(a PRIMARY KEY, b TEXT); + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t1 VALUES(2, 'two'); + BEGIN; + SELECT * FROM t1; +} {wal 1 one 2 two} + +do_test 2.2 { + execsql { + SELECT * FROM t1; + INSERT INTO t1 VALUES(3, 'three'); + } db2 +} {1 one 2 two} + +do_catchsql_test 2.3 { + INSERT INTO t1 VALUES('x', 'x') +} {1 {database is locked}} + +do_test 2.4 { + list [sqlite3_errcode db] [sqlite3_extended_errcode db] +} {SQLITE_BUSY SQLITE_BUSY_SNAPSHOT} + +do_execsql_test 2.5 { + SELECT * FROM t1; + COMMIT; + INSERT INTO t1 VALUES('x', 'x') +} {1 one 2 two} + +proc test3 {prefix} { + do_test $prefix.1 { + execsql { SELECT count(*) FROM t1 } + } {0} + do_test $prefix.2 { + execsql { INSERT INTO t1 VALUES('x', 'x') } db2 + } {} + do_test $prefix.3 { + execsql { INSERT INTO t1 VALUES('y', 'y') } + } {} + do_test $prefix.4 { + execsql { SELECT count(*) FROM t1 } + } {2} +} + +do_execsql_test 2.6.1 { DELETE FROM t1 } +test3 2.6.2 + +db func test3 test3 +do_execsql_test 2.6.3 { DELETE FROM t1 } +db eval {SELECT test3('2.6.4')} + +do_test 2.x { + db2 close +} {} + +#------------------------------------------------------------------------- +# Check that if BEGIN IMMEDIATE fails, it does not leave the user with +# an open read-transaction (unless one was already open before the BEGIN +# IMMEDIATE). Even if there are other active VMs. +# + +proc test4 {prefix} { + do_test $prefix.1 { + catchsql { BEGIN IMMEDIATE } + } {1 {database is locked}} + + do_test $prefix.2 { + execsql { COMMIT } db2 + } {} + + do_test $prefix.3 { + execsql { BEGIN IMMEDIATE } + } {} + do_test $prefix.4 { + execsql { COMMIT } + } {} +} + +reset_db +sqlite3 db2 test.db +do_execsql_test 3.1 { + PRAGMA journal_mode = WAL; + CREATE TABLE ab(a PRIMARY KEY, b); +} {wal} + +do_test 3.2.1 { + execsql { + BEGIN; + INSERT INTO ab VALUES(1, 2); + } db2 +} {} +test4 3.2.2 + +db func test4 test4 +do_test 3.3.1 { + execsql { + BEGIN; + INSERT INTO ab VALUES(3, 4); + } db2 +} {} + +db eval {SELECT test4('3.3.2')} + +do_test 3.x { + db2 close +} {} + +#------------------------------------------------------------------------- +# Check that if a wal file has been partially checkpointed, no frames are +# read from the checkpointed part. +# +reset_db +do_execsql_test 4.1 { + PRAGMA page_size = 1024; + PRAGMA journal_mode = wal; + CREATE TABLE t1(a, b); + CREATE TABLE t2(a, b); + PRAGMA wal_checkpoint = truncate; +} {wal 0 0 0} + +do_test 4.2 { + execsql { INSERT INTO t1 VALUES(1, 2) } + file size test.db-wal +} [wal_file_size 1 1024] + +do_test 4.3 { + sqlite3 db2 test.db + execsql { + BEGIN; + INSERT INTO t2 VALUES(3, 4); + } + execsql { PRAGMA wal_checkpoint = passive } db2 +} {0 1 1} + +do_test 4.3 { + execsql { COMMIT } + db2 close + hexio_write test.db-wal 0 [string repeat 00 2000] + sqlite3 db2 test.db +} {} + +do_test 4.4.1 { + catchsql { SELECT * FROM t1 } db2 +} {0 {1 2}} +do_test 4.4.2 { + catchsql { SELECT * FROM t2 } db2 +} {1 {database disk image is malformed}} + +#------------------------------------------------------------------------- +# Confirm that it is possible to get an SQLITE_BUSY_SNAPSHOT error from +# "BEGIN EXCLUSIVE" if the connection already has an open read-transaction. +# +db close +db2 close +reset_db +sqlite3 db2 test.db +do_execsql_test 5.1 { + PRAGMA journal_mode = wal; + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); +} {wal} +do_test 5.2 { + set res [list] + db eval { + SELECT * FROM t1 + } { + if {$x==1} { + db2 eval { INSERT INTO t1 VALUES(5, 6) } + } + if {$x==3} { + set res [catchsql {BEGIN EXCLUSIVE}] + lappend res [sqlite3_extended_errcode db] + } + } + set res +} {1 {database is locked} SQLITE_BUSY_SNAPSHOT} + + + +finish_test |