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 implements regression tests for SQLite library. The
12 # focus of this file is testing the operation of the library in
13 # "PRAGMA journal_mode=WAL" mode.
16 set testdir [file dirname $argv0]
17 source $testdir/tester.tcl
18 source $testdir/lock_common.tcl
19 source $testdir/malloc_common.tcl
20 source $testdir/wal_common.tcl
23 ifcapable !wal {finish_test ; return }
30 proc xSync {method file args} {
31 if {[file tail $file]=="test.db-wal"} {
37 #-------------------------------------------------------------------------
38 # Test that if IOCAP_SEQUENTIAL is set, the wal-header is not synced to
39 # disk immediately after it is written.
41 sqlite3 db test.db -vfs tvfs
43 PRAGMA auto_vacuum = 0;
44 PRAGMA journal_mode = wal;
45 PRAGMA synchronous = normal;
46 CREATE TABLE t1(a, b, c);
47 INSERT INTO t1 VALUES(1, 2, 3);
48 INSERT INTO t1 VALUES(4, 5, 6);
49 INSERT INTO t1 VALUES(7, 8, 9);
50 PRAGMA wal_checkpoint;
55 execsql { INSERT INTO t1 VALUES(10, 11, 12) }
60 tvfs devchar sequential
61 sqlite3 db test.db -vfs tvfs
63 PRAGMA synchronous = normal;
64 INSERT INTO t1 VALUES(13, 14, 15);
65 INSERT INTO t1 VALUES(16, 17, 18);
66 PRAGMA wal_checkpoint;
71 execsql { INSERT INTO t1 VALUES(10, 11, 12) }
75 #-------------------------------------------------------------------------
76 # Test that "PRAGMA journal_size_limit" works in wal mode.
80 PRAGMA journal_size_limit = 10000;
82 PRAGMA journal_mode = wal;
84 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
86 INSERT INTO t1 SELECT randomblob(750) FROM s;
89 expr [file size test.db-wal]>12000
93 PRAGMA wal_checkpoint;
94 INSERT INTO t1 VALUES(randomblob(750));
100 PRAGMA journal_size_limit = 8000;
101 PRAGMA wal_checkpoint;
102 INSERT INTO t1 VALUES(randomblob(750));
104 file size test.db-wal
107 #-------------------------------------------------------------------------
108 # Test that a checkpoint may be interrupted using sqlite3_interrupt().
109 # And that the error code is SQLITE_NOMEM, not SQLITE_INTERRUPT, if
110 # an OOM error occurs just before the sqlite3_interrupt() call.
114 sqlite3 db test.db -vfs tvfs
117 do_execsql_test 3.0 {
119 PRAGMA journal_mode = wal;
121 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
123 INSERT INTO t1 SELECT randomblob(750) FROM s;
129 proc xWrite {method file args} {
130 if {[file tail $file]=="test.db"} {
139 do_catchsql_test 3.1 {
140 PRAGMA wal_checkpoint
144 proc xWrite {method file args} {
145 if {[file tail $file]=="test.db"} {
148 sqlite3_memdebug_fail 1 -repeat 0
149 # For this test to pass, the following statement must call malloc() at
150 # least once. Even if the lookaside is enabled.
151 set ::xwrite_stmt_res [catchsql { SELECT hex(randomblob(4000)) }]
158 set ::xwrite_stmt_res ""
159 do_catchsql_test 3.2 {
160 PRAGMA wal_checkpoint
161 } {1 {out of memory}}
163 set ::xwrite_stmt_res
164 } {1 {out of memory}}
165 unset ::xwrite_stmt_res
167 #-------------------------------------------------------------------------
172 sqlite3 db test.db -vfs tvfs
175 PRAGMA journal_mode = wal;
177 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
179 INSERT INTO t1 SELECT randomblob(750) FROM s;
186 proc xShmMap {method file args} {
187 return SQLITE_READONLY
189 sqlite3 db test.db -vfs tvfs
190 do_catchsql_test 4.1 {
191 SELECT count(*) FROM t1
192 } {1 {attempt to write a readonly database}}
195 tvfs filter {xShmMap xShmLock}
196 proc xShmMap {method file name args} {
198 xShmMap { return SQLITE_READONLY }
200 if {$args == "{0 1 lock shared}"} {
202 if {$::cnt>0} { return SQLITE_BUSY }
208 do_catchsql_test 4.2 {
209 SELECT count(*) FROM t1
210 } {1 {attempt to write a readonly database}}
212 #-------------------------------------------------------------------------
216 sqlite3 db test.db -vfs tvfs
218 do_execsql_test 5.0 {
219 PRAGMA auto_vacuum = 0;
220 PRAGMA page_size = 1024;
222 PRAGMA journal_mode = wal;
224 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
226 INSERT INTO t1 SELECT randomblob(750) FROM s;
229 do_execsql_test 5.1 {
230 SELECT count(*) FROM t1
234 vfs_set_readmark db main 1 100
235 vfs_set_readmark db main 2 100
236 vfs_set_readmark db main 3 100
237 vfs_set_readmark db main 4 100
240 do_execsql_test 5.3 {
241 SELECT count(*) FROM t1
245 list [vfs_set_readmark db main 1] \
246 [vfs_set_readmark db main 2] \
247 [vfs_set_readmark db main 3] \
248 [vfs_set_readmark db main 4]
254 proc xShmLock {args} {
256 if {$::cnt>0} { return SQLITE_BUSY }
261 vfs_set_readmark db main 1 100
262 execsql { SELECT count(*) FROM t1 }
265 vfs_set_readmark db main 1 100
266 vfs_set_readmark db main 2 100
267 vfs_set_readmark db main 3 100
268 vfs_set_readmark db main 4 100
270 tvfs script xShmMapLock
271 tvfs filter {xShmLock xShmMap}
272 proc xShmMapLock {method args} {
273 if {$method=="xShmMap"} {
274 return "SQLITE_READONLY"
279 sqlite3 db2 test.db -vfs tvfs
282 list [catch { execsql { SELECT count(*) FROM t1 } db2 } msg] $msg
283 } {1 {attempt to write a readonly database}}
286 vfs_set_readmark db main 1 1
289 list [catch { execsql { SELECT count(*) FROM t1 } db2 } msg] $msg
294 #-------------------------------------------------------------------------
295 # Cause an SQLITE_PROTOCOL while attempting to restart the wal file.
300 sqlite3 db test.db -vfs tvfs
301 do_execsql_test 6.0 {
302 PRAGMA auto_vacuum = 0;
303 PRAGMA page_size = 1024;
305 PRAGMA journal_mode = wal;
307 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
309 INSERT INTO t1 SELECT randomblob(750) FROM s;
313 execsql { PRAGMA wal_checkpoint }
320 proc xShmLock {method file handle spec} {
321 if {$::flag && [lrange $spec 2 end]=="lock shared"} {
324 if {$spec=="3 1 unlock shared"} {
330 puts "# WARNING: This next test takes around 12 seconds"
331 do_catchsql_test 6.2 {
332 INSERT INTO t1 VALUES(1);
333 } {1 {locking protocol}}
335 #-------------------------------------------------------------------------
336 # Check that a checkpoint fails if it cannot get the CHECKPOINTER lock
341 sqlite3 db test.db -vfs tvfs
342 do_execsql_test 7.0 {
343 PRAGMA auto_vacuum = 0;
344 PRAGMA page_size = 1024;
346 PRAGMA journal_mode = wal;
348 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
350 INSERT INTO t1 SELECT randomblob(750) FROM s;
355 proc xShmLock {method file handle spec} {
356 if {$spec=="1 1 lock exclusive"} {
362 do_execsql_test 7.1 {
363 PRAGMA wal_checkpoint
366 #-------------------------------------------------------------------------
367 # Check that the page cache is correctly flushed if a checkpointer using
368 # a version 2 VFS makes a checkpoint with an out-of-date cache.
371 testvfs tvfs2 -iversion 2
373 sqlite3 db test.db -vfs tvfs2
374 do_execsql_test 8.0 {
375 PRAGMA auto_vacuum = 0;
376 PRAGMA page_size = 1024;
378 PRAGMA journal_mode = wal;
379 WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20 )
380 INSERT INTO t1 SELECT randomblob(75) FROM s;
383 do_execsql_test 8.1 { SELECT count(*) FROM t1 } {20}
386 sqlite3 db2 test.db -vfs tvfs2
388 INSERT INTO t1 VALUES(randomblob(75));
393 do_execsql_test 8.3 {
394 PRAGMA wal_checkpoint;
395 SELECT count(*) FROM t1
400 #-------------------------------------------------------------------------
403 sqlite3 db test.db -vfs tvfs
404 do_execsql_test 9.0 {
405 PRAGMA auto_vacuum = 0;
406 PRAGMA page_size = 1024;
408 PRAGMA journal_mode = wal;
409 WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20 )
410 INSERT INTO t1 SELECT randomblob(75) FROM s;
413 sqlite3 db2 test.db -vfs tvfs
414 tvfs filter {xShmMap xShmLock}
416 proc xShmMap {method file handle args} {
419 return "SQLITE_READONLY_CANTINIT"
422 if {$args=="{3 1 lock shared}"} {
423 return "SQLITE_IOERR"
430 catchsql { SELECT count(*) FROM t1 } db2
431 } {1 {disk I/O error}}