blob: 89b29fd7ac9e3b0bc7df87089f3b6fbd73d82db4 [file] [log] [blame]
dan94e95ea2018-12-24 15:22:47 +00001# 2018 December 6
2#
3# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
5#
6# May you do good and not evil.
7# May you find forgiveness for yourself and forgive others.
8# May you share freely, never taking more than you give.
9#
10#***********************************************************************
11#
12
13set testdir [file dirname $argv0]
14source $testdir/tester.tcl
15
16set testprefix shmlock
17
18ifcapable !wal {finish_test ; return }
19
20sqlite3 db2 test.db
21sqlite3 db3 test.db
22
23do_execsql_test 1.0 {
24 PRAGMA journal_mode = wal;
25 CREATE TABLE t1(a, b);
26 INSERT INTO t1 VALUES(1, 2);
27} {wal}
28do_test 1.1 { execsql { SELECT * FROM t1 } db2 } {1 2}
29do_test 1.2 { execsql { SELECT * FROM t1 } db3 } {1 2}
30
31foreach {tn dbhandle cmd res} {
32 1 db {shared lock 7 1} OK
33 2 db2 {exclusive lock 7 1} BUSY
34 3 db {shared unlock 7 1} OK
35 4 db2 {exclusive lock 7 1} OK
36 5 db {shared lock 7 1} BUSY
37 6 db {exclusive lock 7 1} BUSY
38 7 db2 {exclusive unlock 7 1} OK
39
40 8 db {exclusive lock 0 8} OK
41 9 db {exclusive unlock 0 8} OK
42 10 db2 {exclusive lock 0 8} OK
43 11 db2 {exclusive unlock 0 8} OK
44
45 12 db {shared lock 0 1} OK
46 13 db2 {shared lock 0 1} OK
47 14 db3 {shared lock 0 1} OK
48 15 db3 {shared unlock 0 1} OK
49 16 db3 {exclusive lock 0 1} BUSY
50 17 db2 {shared unlock 0 1} OK
51 18 db3 {exclusive lock 0 1} BUSY
52 19 db {shared unlock 0 1} OK
53 20 db3 {exclusive lock 0 1} OK
54 21 db3 {exclusive unlock 0 1} OK
55
56 22 db {shared lock 3 1} OK
57 23 db2 {exclusive lock 2 2} BUSY
58 24 db {shared lock 2 1} OK
59 25 db2 {exclusive lock 0 5} BUSY
60 26 db2 {exclusive lock 0 4} BUSY
61 27 db2 {exclusive lock 0 3} BUSY
62 28 db {shared unlock 3 1} OK
63 29 db2 {exclusive lock 2 2} BUSY
64 28 db {shared unlock 2 1} OK
65 29 db2 {exclusive lock 2 2} OK
66 29 db2 {exclusive unlock 2 2} OK
67} {
68 do_test 1.3.$tn [list vfs_shmlock $dbhandle main {*}$cmd] "SQLITE_$res"
69}
70
71db close
72db2 close
73db3 close
74
75if {[permutation]=="unix-excl"} {
76 do_test 2.0 {
77 for {set i 0} {$i < 256} {incr i} {
78 sqlite3 db$i test.db
79 execsql { SELECT * FROM t1 } db$i
80 }
81 for {set i 0} {$i < 255} {incr i} {
82 set rc [vfs_shmlock db$i main shared lock 4 1]
83 if {$rc != "SQLITE_OK"} { error $rc }
84 }
85
86 vfs_shmlock db255 main shared lock 4 1
87 } {SQLITE_BUSY}
88
89 do_test 2.1 { vfs_shmlock db255 main exclusive lock 4 1 } SQLITE_BUSY
90 do_test 2.2 { vfs_shmlock db0 main shared unlock 4 1 } SQLITE_OK
91 do_test 2.3 { vfs_shmlock db255 main shared lock 4 1 } SQLITE_OK
92 do_test 2.4 { vfs_shmlock db255 main shared unlock 4 1 } SQLITE_OK
93 do_test 2.5 { vfs_shmlock db255 main exclusive lock 4 1 } SQLITE_BUSY
94
95 do_test 2.6 {
96 for {set i 1} {$i < 255} {incr i} {
97 set rc [vfs_shmlock db255 main exclusive lock 4 1]
98 if {$rc != "SQLITE_BUSY"} { error $rc }
99 set rc [vfs_shmlock db$i main shared unlock 4 1]
100 if {$rc != "SQLITE_OK"} { error $rc }
101 }
102
103 vfs_shmlock db255 main exclusive lock 4 1
104 } {SQLITE_OK}
105
106 vfs_shmlock db255 main exclusive unlock 4 1
107
108 for {set i 0} {$i < 256} {incr i} {
109 db$i close
110 }
111}
112
113sqlite3 db0 test.db
114sqlite3 db1 test.db
115do_test 3.1 { execsql { SELECT * FROM t1 } db0 } {1 2}
116do_test 3.2 { execsql { SELECT * FROM t1 } db1 } {1 2}
drh94e02d92019-01-03 16:00:23 +0000117if {$tcl_platform(platform)=="windows"} {
118 set isWindows 1
119} else {
120 set isWindows 0
121}
dan94e95ea2018-12-24 15:22:47 +0000122
123set L(0) {n n n n n n n n}
124set L(1) {n n n n n n n n}
125proc random_lock_test {idx} {
126 global L
127 set iSlot [expr int(rand()*8)]
128 if {[expr int(rand()*2)]} {
129 # Unlock operation
130 if {[lindex $L($idx) $iSlot]!="n"} {
131 vfs_shmlock db$idx main [lindex $L($idx) $iSlot] unlock $iSlot 1
132 lset L($idx) $iSlot n
133 }
134 } else {
135 # Lock operation
136 if {[lindex $L($idx) $iSlot]=="n"} {
137 set locktype [lindex {e s} [expr int(rand()*2)]]
138 set n 1
139 if {$locktype=="e"} {
140 for {set l $iSlot} {$l<8 && [lindex $L($idx) $l]=="n"} {incr l} {}
141 set n [expr int(rand()*($l-$iSlot))+1]
drh94e02d92019-01-03 16:00:23 +0000142 # The LockFile() and UnlockFile() apis on windows require that
143 # every unlock correspond exactly to a prior lock. Hence, we cannot
144 # lock arbitrary ranges in this test on windows.
145 if {$::isWindows} {set n 1}
dan94e95ea2018-12-24 15:22:47 +0000146 # puts "iSlot=$iSlot l=$l L=$L($idx)"
147 # puts "$iSlot $n"
148 }
149 set res [vfs_shmlock db$idx main $locktype lock $iSlot $n]
150
151 set bBusy 0
152 for {set i $iSlot} {$i<($iSlot+$n)} {incr i} {
153 set other [lindex $L([expr ($idx+1)%2]) $i]
154 if {($other!="n" && $locktype=="e")||($other=="e" && $locktype=="s")} {
155 if {$res != "SQLITE_BUSY"} { error "BUSY not detected" }
156 set bBusy 1
157 break
158 }
159 }
160
161 if {$bBusy==0} {
162 if {$res != "SQLITE_OK"} { error "BUSY false-positive" }
163 for {set i $iSlot} {$i<($iSlot+$n)} {incr i} {
164 lset L($idx) $i $locktype
165 }
166 }
167 }
168 }
169}
170
171set nStep 100000
172for {set i 0} {$i < $nStep} {incr i} {
173 random_lock_test 0
174 random_lock_test 1
175}
176
177db0 close
178db1 close
179
180finish_test