diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 14:07:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 14:07:11 +0000 |
commit | 63847496f14c813a5d80efd5b7de0f1294ffe1e3 (patch) | |
tree | 01c7571c7c762ceee70638549a99834fdd7c411b /test/walprotocol.test | |
parent | Initial commit. (diff) | |
download | sqlite3-63847496f14c813a5d80efd5b7de0f1294ffe1e3.tar.xz sqlite3-63847496f14c813a5d80efd5b7de0f1294ffe1e3.zip |
Adding upstream version 3.45.1.upstream/3.45.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/walprotocol.test')
-rw-r--r-- | test/walprotocol.test | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/test/walprotocol.test b/test/walprotocol.test new file mode 100644 index 0000000..a262cdd --- /dev/null +++ b/test/walprotocol.test @@ -0,0 +1,201 @@ +# 2016 February 4 +# +# 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. +# +# More specifically, it tests "locking protocol" errors - errors that +# may be caused if one or more SQLite clients does not follow the expected +# locking protocol when accessing a wal-mode database. These tests take +# quite a while to run. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/lock_common.tcl +source $testdir/wal_common.tcl +ifcapable !wal {finish_test ; return } + +set testprefix walprotocol + +#------------------------------------------------------------------------- +# When recovering the contents of a WAL file, a process obtains the WRITER +# lock, then locks all other bytes before commencing recovery. If it fails +# to lock all other bytes (because some other process is holding a read +# lock) it should retry up to 100 times. Then return SQLITE_PROTOCOL to the +# caller. Test this (test case 1.3). +# +# Also test the effect of hitting an SQLITE_BUSY while attempting to obtain +# the WRITER lock (should be the same). Test case 1.4. +# +do_execsql_test 1.0 { + PRAGMA journal_mode = wal; + CREATE TABLE x(y); + INSERT INTO x VALUES('z'); +} {wal} + +proc lock_callback {method filename handle lock} { + lappend ::locks $lock +} +do_test 1.1 { + testvfs T + T filter xShmLock + T script lock_callback + set ::locks [list] + sqlite3 db test.db -vfs T + execsql { SELECT * FROM x } + lrange $::locks 0 11 +} [list {0 1 lock exclusive} {1 2 lock exclusive} \ + {4 1 lock exclusive} {4 1 unlock exclusive} \ + {5 1 lock exclusive} {5 1 unlock exclusive} \ + {6 1 lock exclusive} {6 1 unlock exclusive} \ + {7 1 lock exclusive} {7 1 unlock exclusive} \ + {1 2 unlock exclusive} \ + {0 1 unlock exclusive} \ +] +do_test 1.2 { + db close + set ::locks [list] + sqlite3 db test.db -vfs T + execsql { SELECT * FROM x } + lrange $::locks 0 11 +} [list {0 1 lock exclusive} {1 2 lock exclusive} \ + {4 1 lock exclusive} {4 1 unlock exclusive} \ + {5 1 lock exclusive} {5 1 unlock exclusive} \ + {6 1 lock exclusive} {6 1 unlock exclusive} \ + {7 1 lock exclusive} {7 1 unlock exclusive} \ + {1 2 unlock exclusive} \ + {0 1 unlock exclusive} \ +] +proc lock_callback {method filename handle lock} { + if {$lock == "1 2 lock exclusive"} { return SQLITE_BUSY } + return SQLITE_OK +} +puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times." +puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite" +puts "# is built on unix without HAVE_USLEEP defined, it may be much longer." +do_test 1.3 { + db close + set ::locks [list] + sqlite3 db test.db -vfs T + catchsql { SELECT * FROM x } +} {1 {locking protocol}} + +puts "# Warning: Same again!" +proc lock_callback {method filename handle lock} { + if {$lock == "0 1 lock exclusive"} { return SQLITE_BUSY } + return SQLITE_OK +} +do_test 1.4 { + db close + set ::locks [list] + sqlite3 db test.db -vfs T + catchsql { SELECT * FROM x } +} {1 {locking protocol}} + +puts "# Warning: Third time!" +proc lock_callback {method filename handle lock} { + if {$lock == "4 4 lock exclusive"} { return SQLITE_BUSY } + return SQLITE_OK +} +do_test 1.5 { + db close + set ::locks [list] + sqlite3 db test.db -vfs T + catchsql { SELECT * FROM x } +} {0 z} +db close +T delete + +#------------------------------------------------------------------------- +# +do_test 2.1 { + forcedelete test.db test.db-journal test.db wal + sqlite3 db test.db + sqlite3 db2 test.db + execsql { + PRAGMA auto_vacuum = off; + PRAGMA journal_mode = WAL; + CREATE TABLE b(c); + INSERT INTO b VALUES('Tehran'); + INSERT INTO b VALUES('Qom'); + INSERT INTO b VALUES('Markazi'); + PRAGMA wal_checkpoint; + } +} {wal 0 5 5} +do_test 2.2 { + execsql { SELECT * FROM b } +} {Tehran Qom Markazi} +do_test 2.3 { + db eval { SELECT * FROM b } { + db eval { INSERT INTO b VALUES('Qazvin') } + set r [db2 eval { SELECT * FROM b }] + break + } + set r +} {Tehran Qom Markazi Qazvin} +do_test 2.4 { + execsql { + INSERT INTO b VALUES('Gilan'); + INSERT INTO b VALUES('Ardabil'); + } +} {} +db2 close + +faultsim_save_and_close +testvfs T -default 1 +faultsim_restore_and_reopen +T filter xShmLock +T script lock_callback + +proc lock_callback {method file handle spec} { + if {$spec == "1 2 unlock exclusive"} { + T filter {} + set ::r [catchsql { SELECT * FROM b } db2] + } +} +sqlite3 db test.db +sqlite3 db2 test.db +puts "# Warning: Another slow test!" +do_test 2.5 { + execsql { SELECT * FROM b } +} {Tehran Qom Markazi Qazvin Gilan Ardabil} +do_test 2.6 { + set ::r +} {0 {Tehran Qom Markazi Qazvin Gilan Ardabil}} + +db close +db2 close + +faultsim_restore_and_reopen +sqlite3 db2 test.db +T filter xShmLock +T script lock_callback +proc lock_callback {method file handle spec} { + if {$spec == "1 2 unlock exclusive"} { + T filter {} + set ::r [catchsql { SELECT * FROM b } db2] + } +} +unset ::r +puts "# Warning: Last one!" +do_test 2.7 { + execsql { SELECT * FROM b } +} {Tehran Qom Markazi Qazvin Gilan Ardabil} +do_test 2.8 { + set ::r +} {0 {Tehran Qom Markazi Qazvin Gilan Ardabil}} + +db close +db2 close +T delete + +finish_test |