blob: 89b29fd7ac9e3b0bc7df87089f3b6fbd73d82db4 [file] [log] [blame]
# 2018 December 6
#
# 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
set testprefix shmlock
ifcapable !wal {finish_test ; return }
sqlite3 db2 test.db
sqlite3 db3 test.db
do_execsql_test 1.0 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
} {wal}
do_test 1.1 { execsql { SELECT * FROM t1 } db2 } {1 2}
do_test 1.2 { execsql { SELECT * FROM t1 } db3 } {1 2}
foreach {tn dbhandle cmd res} {
1 db {shared lock 7 1} OK
2 db2 {exclusive lock 7 1} BUSY
3 db {shared unlock 7 1} OK
4 db2 {exclusive lock 7 1} OK
5 db {shared lock 7 1} BUSY
6 db {exclusive lock 7 1} BUSY
7 db2 {exclusive unlock 7 1} OK
8 db {exclusive lock 0 8} OK
9 db {exclusive unlock 0 8} OK
10 db2 {exclusive lock 0 8} OK
11 db2 {exclusive unlock 0 8} OK
12 db {shared lock 0 1} OK
13 db2 {shared lock 0 1} OK
14 db3 {shared lock 0 1} OK
15 db3 {shared unlock 0 1} OK
16 db3 {exclusive lock 0 1} BUSY
17 db2 {shared unlock 0 1} OK
18 db3 {exclusive lock 0 1} BUSY
19 db {shared unlock 0 1} OK
20 db3 {exclusive lock 0 1} OK
21 db3 {exclusive unlock 0 1} OK
22 db {shared lock 3 1} OK
23 db2 {exclusive lock 2 2} BUSY
24 db {shared lock 2 1} OK
25 db2 {exclusive lock 0 5} BUSY
26 db2 {exclusive lock 0 4} BUSY
27 db2 {exclusive lock 0 3} BUSY
28 db {shared unlock 3 1} OK
29 db2 {exclusive lock 2 2} BUSY
28 db {shared unlock 2 1} OK
29 db2 {exclusive lock 2 2} OK
29 db2 {exclusive unlock 2 2} OK
} {
do_test 1.3.$tn [list vfs_shmlock $dbhandle main {*}$cmd] "SQLITE_$res"
}
db close
db2 close
db3 close
if {[permutation]=="unix-excl"} {
do_test 2.0 {
for {set i 0} {$i < 256} {incr i} {
sqlite3 db$i test.db
execsql { SELECT * FROM t1 } db$i
}
for {set i 0} {$i < 255} {incr i} {
set rc [vfs_shmlock db$i main shared lock 4 1]
if {$rc != "SQLITE_OK"} { error $rc }
}
vfs_shmlock db255 main shared lock 4 1
} {SQLITE_BUSY}
do_test 2.1 { vfs_shmlock db255 main exclusive lock 4 1 } SQLITE_BUSY
do_test 2.2 { vfs_shmlock db0 main shared unlock 4 1 } SQLITE_OK
do_test 2.3 { vfs_shmlock db255 main shared lock 4 1 } SQLITE_OK
do_test 2.4 { vfs_shmlock db255 main shared unlock 4 1 } SQLITE_OK
do_test 2.5 { vfs_shmlock db255 main exclusive lock 4 1 } SQLITE_BUSY
do_test 2.6 {
for {set i 1} {$i < 255} {incr i} {
set rc [vfs_shmlock db255 main exclusive lock 4 1]
if {$rc != "SQLITE_BUSY"} { error $rc }
set rc [vfs_shmlock db$i main shared unlock 4 1]
if {$rc != "SQLITE_OK"} { error $rc }
}
vfs_shmlock db255 main exclusive lock 4 1
} {SQLITE_OK}
vfs_shmlock db255 main exclusive unlock 4 1
for {set i 0} {$i < 256} {incr i} {
db$i close
}
}
sqlite3 db0 test.db
sqlite3 db1 test.db
do_test 3.1 { execsql { SELECT * FROM t1 } db0 } {1 2}
do_test 3.2 { execsql { SELECT * FROM t1 } db1 } {1 2}
if {$tcl_platform(platform)=="windows"} {
set isWindows 1
} else {
set isWindows 0
}
set L(0) {n n n n n n n n}
set L(1) {n n n n n n n n}
proc random_lock_test {idx} {
global L
set iSlot [expr int(rand()*8)]
if {[expr int(rand()*2)]} {
# Unlock operation
if {[lindex $L($idx) $iSlot]!="n"} {
vfs_shmlock db$idx main [lindex $L($idx) $iSlot] unlock $iSlot 1
lset L($idx) $iSlot n
}
} else {
# Lock operation
if {[lindex $L($idx) $iSlot]=="n"} {
set locktype [lindex {e s} [expr int(rand()*2)]]
set n 1
if {$locktype=="e"} {
for {set l $iSlot} {$l<8 && [lindex $L($idx) $l]=="n"} {incr l} {}
set n [expr int(rand()*($l-$iSlot))+1]
# The LockFile() and UnlockFile() apis on windows require that
# every unlock correspond exactly to a prior lock. Hence, we cannot
# lock arbitrary ranges in this test on windows.
if {$::isWindows} {set n 1}
# puts "iSlot=$iSlot l=$l L=$L($idx)"
# puts "$iSlot $n"
}
set res [vfs_shmlock db$idx main $locktype lock $iSlot $n]
set bBusy 0
for {set i $iSlot} {$i<($iSlot+$n)} {incr i} {
set other [lindex $L([expr ($idx+1)%2]) $i]
if {($other!="n" && $locktype=="e")||($other=="e" && $locktype=="s")} {
if {$res != "SQLITE_BUSY"} { error "BUSY not detected" }
set bBusy 1
break
}
}
if {$bBusy==0} {
if {$res != "SQLITE_OK"} { error "BUSY false-positive" }
for {set i $iSlot} {$i<($iSlot+$n)} {incr i} {
lset L($idx) $i $locktype
}
}
}
}
}
set nStep 100000
for {set i 0} {$i < $nStep} {incr i} {
random_lock_test 0
random_lock_test 1
}
db0 close
db1 close
finish_test