namespace changes and fixes for non-amalgamated builds
[sqlcipher.git] / test / busy2.test
blob61fb8496a82bea43dc72b9301a9c6ae1b9f925f2
1 # 2020 June 30
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 #***********************************************************************
11 # This file test the busy handler
15 set testdir [file dirname $argv0]
16 source $testdir/tester.tcl
17 source $testdir/lock_common.tcl
18 set testprefix busy2
20 do_multiclient_test tn {
21   do_test 1.$tn.0 {
22     sql2 {
23       CREATE TABLE t1(a, b);
24       PRAGMA journal_mode = wal;
25       INSERT INTO t1 VALUES('A', 'B');
26     }
27   } {wal}
29   do_test 1.$tn.1 {
30     code1 { db timeout 1000 }
31     sql1 { SELECT * FROM t1 }
32   } {A B}
34   do_test 1.$tn.2 {
35     sql2 {
36       BEGIN;
37         INSERT INTO t1 VALUES('C', 'D');
38     }
39   } {}
41   do_test 1.$tn.3 {
42     set us [lindex [time { catch { sql1 { BEGIN EXCLUSIVE } } }] 0]
43     expr {$us>950000 && $us<1500000}
44   } {1}
46   do_test 1.$tn.4 {
47     sql2 {
48       COMMIT
49     }
50   } {}
53 #-------------------------------------------------------------------------
55 do_multiclient_test tn {
56   # Make the db a WAL mode db. And add a table and a row to it. Then open
57   # a second connection within process 1. Process 1 now has connections
58   # [db] and [db1.2], process 2 has connection [db2] only.
59   #
60   # Configure all connections to use a 1000 ms timeout.
61   #
62   do_test 2.$tn.0 {
63     code1 {
64       sqlite3 db1.2 test.db
65     }
66     sql1 {
67       PRAGMA auto_vacuum = off;
68       PRAGMA journal_mode = wal;
69       CREATE TABLE t1(a, b);
70       INSERT INTO t1 VALUES(1, 2);
71     }
72     code2 {
73       db2 timeout 1000
74     }
75     code1 {
76       db1.2 timeout 1000
77       db    timeout 1000
78       db1.2 eval {SELECT * FROM t1}
79     }
80   } {1 2}
82   # Take a read lock with [db] in process 1.
83   #
84   do_test 2.$tn.1 {
85     sql1 {
86       BEGIN;
87         SELECT * FROM t1;
88     }
89   } {1 2}
91   # Insert a row using [db2] in process 2. Then try a passive checkpoint.
92   # It fails to checkpoint the final frame (due to the readlock taken by
93   # [db]), and returns in less than 250ms.
94   do_test 2.$tn.2 {
95     sql2 { INSERT INTO t1 VALUES(3, 4) }
96     set us [lindex [time {
97       set res [code2 { db2 eval { PRAGMA wal_checkpoint } }]
98     }] 0]
99     list [expr $us < 250000] $res
100   } {1 {0 4 3}}
102   # Now try a FULL checkpoint with [db2]. It returns SQLITE_BUSY. And takes
103   # over 950ms to do so.
104   do_test 2.$tn.3 {
105     set us [lindex [time {
106       set res [code2 { db2 eval { PRAGMA wal_checkpoint = FULL } }]
107     }] 0]
108     list [expr $us > 950000] $res
109   } {1 {1 4 3}}
111   # Passive checkpoint with [db1.2] (process 1). No SQLITE_BUSY, returns
112   # in under 250ms.
113   do_test 2.$tn.4 {
114     set us [lindex [time {
115       set res [code1 { db1.2 eval { PRAGMA wal_checkpoint } }]
116     }] 0]
117     list [expr $us < 250000] $res
118   } {1 {0 4 3}}
120   # Full checkpoint with [db1.2] (process 1). SQLITE_BUSY returned in
121   # a bit over 950ms.
122   do_test 2.$tn.5 {
123     set us [lindex [time {
124       set res [code1 { db1.2 eval { PRAGMA wal_checkpoint = FULL } }]
125     }] 0]
126     list [expr $us > 950000] $res
127   } {1 {1 4 3}}
129   code1 {
130     db1.2 close
131   }
134 #-------------------------------------------------------------------------
135 # Check that even if the busy-handler fails (returns zero) within a
136 # call to sqlite3_prepare() (or _v2(), or _v3()), it is still invoked
137 # the next time an SQLITE_BUSY is encountered.
139 do_multiclient_test tn {
140   code1 {
141     set ::busy_called 0
142     proc busy {args} {
143       if {$::busy_called} { return 1 }
144       set ::busy_called 1
145       return 0
146     }
147     db busy busy
148   }
150   do_test 3.$tn.1 {
151     sql2 {
152       CREATE TABLE t1(x);
153       BEGIN EXCLUSIVE;
154         INSERT INTO t1 VALUES('x');
155     }
156   } {}
158   do_test 3.$tn.2 {
159     set ::busy_called 0
160     list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
161   } {1 1}
163   do_test 3.$tn.3 {
164     set ::busy_called 0
165     list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
166   } {1 1}
170 finish_test