1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-04-26 11:28:58 +03:00
sqlite/test/walsetlk.test
jan.nijtmans 87b90921b6 In Tcl, always use eq/ne for comparing strings, not ==/!=
FossilOrigin-Name: f96a5346e3e890adfdc94a682688c2c15893e50fbaf2a26e5ef39cda8b331ee4
2025-03-27 14:32:57 +00:00

351 lines
7.0 KiB
Plaintext

# 2020 May 06
#
# 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.
#
#***********************************************************************
#
# TESTRUNNER: slow
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix walsetlk
ifcapable !wal {finish_test ; return }
db timeout 1000
#-------------------------------------------------------------------------
# 1.*: Test that nothing goes wrong if recovery is forced while opening
# a write transaction or performing a checkpoint with blocking locks.
#
do_execsql_test 1.0 {
CREATE TABLE t1(x, y);
PRAGMA journal_mode = wal;
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
INSERT INTO t1 VALUES(7, 8);
} {wal}
sqlite3 db2 test.db
db2 timeout 1000
do_execsql_test -db db2 1.1 {
SELECT * FROM t1
} {1 2 3 4 5 6 7 8}
set fd [open test.db-shm r+]
puts $fd "blahblahblahblah"
flush $fd
do_execsql_test 1.2 {
BEGIN;
INSERT INTO t1 VALUES(9, 10);
}
do_execsql_test -db db2 1.3 {
SELECT * FROM t1
} {1 2 3 4 5 6 7 8}
do_test 1.4 {
list [catch {db2 eval { BEGIN EXCLUSIVE }} msg] $msg
} {1 {database is locked}}
do_execsql_test 1.5 { COMMIT }
do_execsql_test -db db2 1.6 {
SELECT * FROM t1
} {1 2 3 4 5 6 7 8 9 10}
puts $fd "blahblahblahblah"
flush $fd
do_execsql_test -db db2 1.7 {
PRAGMA wal_checkpoint = TRUNCATE
} {0 0 0}
do_test 1.8 {
file size test.db-wal
} 0
close $fd
db close
db2 close
#-------------------------------------------------------------------------
do_multiclient_test tn {
testvfs tvfs -fullshm 1
db close
sqlite3 db test.db -vfs tvfs
tvfs script xSleep_callback
tvfs filter xSleep
set ::sleep_count 0
proc xSleep_callback {xSleep nMs} {
after [expr $nMs / 1000]
incr ::sleep_count
}
do_test 2.$tn.1 {
sql1 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(s, v);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
}
code1 { db timeout 1100 }
} {}
do_test 2.$tn.2 {
sql2 {
BEGIN;
INSERT INTO t1 VALUES(7, 8);
}
} {}
do_test 2.$tn.3 {
set us [lindex [time { catch {db eval "BEGIN EXCLUSIVE"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
do_test 2.$tn.4 {
sql2 { COMMIT }
sql1 { SELECT * FROM t1 }
} {1 2 3 4 5 6 7 8}
do_test 2.$tn.5 {
sql2 {
BEGIN;
INSERT INTO t1 VALUES(9, 10);
}
} {}
do_test 2.$tn.6 {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
do_test 2.$tn.7 {
sql2 {
COMMIT;
BEGIN;
SELECT * FROM t1;
}
} {1 2 3 4 5 6 7 8 9 10}
do_test 2.$tn.8 {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
do_test 2.$tn.9 {
sql3 {
INSERT INTO t1 VALUES(11, 12);
}
sql2 {
COMMIT;
BEGIN;
SELECT * FROM t1;
}
sql3 {
INSERT INTO t1 VALUES(13, 14);
}
} {}
do_test 2.$tn.10 {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
do_test 2.$tn.11 {
sql3 {
BEGIN;
SELECT * FROM t1;
}
sql1 { INSERT INTO t1 VALUES(15, 16); }
} {}
do_test 2.$tn.12 {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
do_test 2.$tn.13 {
sql2 {
COMMIT;
BEGIN;
SELECT * FROM t1;
}
sql1 { INSERT INTO t1 VALUES(17, 18); }
} {}
do_test 2.$tn.14 {
set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0]
expr $us>1000000 && $us<4000000
} {1}
db close
tvfs delete
# Set bSleep to true if it is expected that the above used xSleep() to
# wait for locks. bSleep is true unless SQLITE_ENABLE_SETLK_TIMEOUT is
# set to 1 and either:
#
# * the OS is windows, or
# * the OS is unix and the tests were run with each connection
# in a separate process.
#
set bSleep 1
if {$::sqlite_options(setlk_timeout)==1} {
if {$::tcl_platform(platform) eq "windows"} {
set bSleep 0
}
if {$::tcl_platform(platform) eq "unix"} {
set bSleep [expr $tn==2]
}
}
do_test 2.$tn.15.$bSleep {
expr $::sleep_count > 0
} $bSleep
}
#-------------------------------------------------------------------------
reset_db
testvfs tvfs -fullshm 1
tvfs script xSleep_callback
tvfs filter xSleep
set ::sleep_count 0
proc xSleep_callback {xSleep nMs} {
after [expr $nMs / 1000]
incr ::sleep_count
breakpoint
}
sqlite3 db2 test.db -vfs tvfs
db2 timeout 1000
do_execsql_test 3.0 {
PRAGMA journal_mode = wal;
CREATE TABLE x1(x, y);
BEGIN;
INSERT INTO x1 VALUES(1, 2);
} {wal}
do_execsql_test -db db2 3.1a {
SELECT * FROM x1
} {}
do_test 3.1b {
list [catch { db2 eval {BEGIN EXCLUSIVE} } msg] $msg
} {1 {database is locked}}
# Set bExpect to true if calls to xSleep() are expected. Such calls are
# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
set bExpect 1
if {$tcl_platform(platform) eq "windows" && $::sqlite_options(setlk_timeout)==1} {
set bExpect 0
}
do_test 3.2 {
expr {$::sleep_count > 0}
} $bExpect
set ::sleep_count 0
do_execsql_test 3.3 {
COMMIT;
}
# Launch a non-blocking testfixture process to write-lock the
# database for 2000 ms.
testfixture_nb done {
sqlite3 db test.db
db eval {
BEGIN EXCLUSIVE;
INSERT INTO x1 VALUES(3, 4);
}
after 2000
db eval {
COMMIT
}
}
after 500 {set ok 1}
vwait ok
db2 timeout 5000
do_test 3.4 {
set t [lindex [time { db2 eval { BEGIN EXCLUSIVE } }] 0]
expr ($t>1000000)
} {1}
# Set bExpect to true if calls to xSleep() are expected. Such calls are
# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
set bExpect 1
if {$::sqlite_options(setlk_timeout)==1} {
set bExpect 0
}
do_test 3.5 {
expr {$::sleep_count > 0}
} $bExpect
do_execsql_test -db db2 3.6 {
INSERT INTO x1 VALUES(5, 6);
COMMIT;
SELECT * FROM x1;
} {1 2 3 4 5 6}
# Launch a non-blocking testfixture process to write-lock the
# database for 2000 ms.
testfixture_nb done {
sqlite3 db test.db
db eval {
BEGIN EXCLUSIVE;
INSERT INTO x1 VALUES(7, 8);
}
after 2000
db eval {
COMMIT
}
db close
}
after 500 {set ok 1}
vwait ok
db2 timeout 0x7FFFFFFF
do_test 3.7 {
set t [lindex [time { db2 eval { BEGIN EXCLUSIVE } }] 0]
expr ($t>1000000)
} {1}
# Set bExpect to true if calls to xSleep() are expected. Such calls are
# expected unless this is an SQLITE_ENABLE_SETLK_TIMEOUT=1 build.
set bExpect 1
if {$::sqlite_options(setlk_timeout)==1} {
set bExpect 0
}
do_test 3.8 {
expr {$::sleep_count > 0}
} $bExpect
do_execsql_test -db db2 3.9 {
INSERT INTO x1 VALUES(9, 10);
COMMIT;
SELECT * FROM x1;
} {1 2 3 4 5 6 7 8 9 10}
db2 close
tvfs delete
finish_test