Fix a case where a corrupt stat4 record could go unrecognized due to integer overflow.
[sqlite.git] / test / shmlock.test
blob89b29fd7ac9e3b0bc7df87089f3b6fbd73d82db4
1 # 2018 December 6
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
13 set testdir [file dirname $argv0]
14 source $testdir/tester.tcl
16 set testprefix shmlock
18 ifcapable !wal {finish_test ; return }
20 sqlite3 db2 test.db
21 sqlite3 db3 test.db
23 do_execsql_test 1.0 {
24   PRAGMA journal_mode = wal;
25   CREATE TABLE t1(a, b);
26   INSERT INTO t1 VALUES(1, 2);
27 } {wal}
28 do_test 1.1 { execsql { SELECT * FROM t1 } db2 } {1 2}
29 do_test 1.2 { execsql { SELECT * FROM t1 } db3 } {1 2}
31 foreach {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
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
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
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"
71 db  close
72 db2 close
73 db3 close
75 if {[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     }
86     vfs_shmlock db255 main shared lock 4 1
87   } {SQLITE_BUSY}
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
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     }
103     vfs_shmlock db255 main exclusive lock 4 1
104   } {SQLITE_OK}
106   vfs_shmlock db255 main exclusive unlock 4 1
108   for {set i 0} {$i < 256} {incr i} {
109     db$i close
110   }
113 sqlite3 db0 test.db
114 sqlite3 db1 test.db
115 do_test 3.1 { execsql { SELECT * FROM t1 } db0 } {1 2}
116 do_test 3.2 { execsql { SELECT * FROM t1 } db1 } {1 2}
117 if {$tcl_platform(platform)=="windows"} {
118   set isWindows 1
119 } else {
120   set isWindows 0
123 set L(0) {n n n n n n n n}
124 set L(1) {n n n n n n n n}
125 proc 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]
142         # 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}
146         # 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]
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       }
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   }
171 set nStep 100000
172 for {set i 0} {$i < $nStep} {incr i} {
173   random_lock_test 0
174   random_lock_test 1
177 db0 close
178 db1 close
180 finish_test