176ed3bc0Sdan# 2010 May 03 276ed3bc0Sdan# 376ed3bc0Sdan# The author disclaims copyright to this source code. In place of 476ed3bc0Sdan# a legal notice, here is a blessing: 576ed3bc0Sdan# 676ed3bc0Sdan# May you do good and not evil. 776ed3bc0Sdan# May you find forgiveness for yourself and forgive others. 876ed3bc0Sdan# May you share freely, never taking more than you give. 976ed3bc0Sdan# 1076ed3bc0Sdan#*********************************************************************** 1176ed3bc0Sdan# This file implements regression tests for SQLite library. The 1276ed3bc0Sdan# focus of this file is testing the operation of the library in 1376ed3bc0Sdan# "PRAGMA journal_mode=WAL" mode. 1476ed3bc0Sdan# 1576ed3bc0Sdan 1676ed3bc0Sdanset testdir [file dirname $argv0] 1776ed3bc0Sdansource $testdir/tester.tcl 1876ed3bc0Sdansource $testdir/malloc_common.tcl 1976ed3bc0Sdan 2076ed3bc0Sdanifcapable !wal {finish_test ; return } 2176ed3bc0Sdan 2276ed3bc0Sdando_malloc_test walfault-oom-1 -sqlbody { 2376ed3bc0Sdan PRAGMA journal_mode = WAL; 2476ed3bc0Sdan CREATE TABLE t1(a, b); 2576ed3bc0Sdan INSERT INTO t1 VALUES(1, 2); 26ef378025Sdan PRAGMA wal_checkpoint; 2776ed3bc0Sdan} 2876ed3bc0Sdan 295e9e482fSdando_malloc_test walfault-oom-2 -tclprep { 305e9e482fSdan execsql { 315e9e482fSdan PRAGMA journal_mode = WAL; 325e9e482fSdan BEGIN; 335e9e482fSdan CREATE TABLE x(y, z, UNIQUE(y, z)); 345e9e482fSdan INSERT INTO x VALUES(randomblob(100), randomblob(100)); 355e9e482fSdan COMMIT; 365e9e482fSdan PRAGMA wal_checkpoint; 375e9e482fSdan 385e9e482fSdan INSERT INTO x SELECT randomblob(100), randomblob(100) FROM x; 395e9e482fSdan INSERT INTO x SELECT randomblob(100), randomblob(100) FROM x; 405e9e482fSdan INSERT INTO x SELECT randomblob(100), randomblob(100) FROM x; 415e9e482fSdan } 425e9e482fSdan file copy -force test.db testX.db 435e9e482fSdan file copy -force test.db-wal testX.db-wal 445e9e482fSdan db close 455e9e482fSdan file rename -force testX.db test.db 465e9e482fSdan file rename -force testX.db-wal test.db-wal 475e9e482fSdan 485e9e482fSdan sqlite3 db test.db 495e9e482fSdan sqlite3_extended_result_codes db 1 505e9e482fSdan sqlite3_db_config_lookaside db 0 0 0 515e9e482fSdan} -sqlbody { 525e9e482fSdan SELECT count(*) FROM x; 535e9e482fSdan} 545e9e482fSdan 55c7991bdfSdan# A [testvfs] callback for the VFS created by [do_shmfault_test]. This 56*8f6097c2Sdan# callback injects SQLITE_IOERR faults into methods for which an entry 57*8f6097c2Sdan# in array ::shmfault_ioerr_methods is defined. For example, to enable 58*8f6097c2Sdan# errors in xShmOpen: 59c7991bdfSdan# 60*8f6097c2Sdan# set ::shmfault_ioerr_methods(xShmOpen) 1 61c7991bdfSdan# 62c7991bdfSdan# Faults are not injected into xShmRelease, xShmClose or xShmLock method 63c7991bdfSdan# calls. The global tcl variables used are: 64c7991bdfSdan# 65c7991bdfSdan# $::shmfault_ioerr_countdown 66c7991bdfSdan# $::shmfault_ioerr_persist 67*8f6097c2Sdan# $::shmfault_ioerr_methods 68c7991bdfSdan# 69c7991bdfSdanproc shmfault_vfs_cb {method args} { 70c7991bdfSdan 71c7991bdfSdan # If ::shmfault_ioerr_countdown is not set, always return SQLITE_OK. 72c7991bdfSdan # 73c7991bdfSdan if {[info exists ::shmfault_ioerr_countdown]==0} { return SQLITE_OK } 74c7991bdfSdan 75*8f6097c2Sdan if {[info exists ::shmfault_ioerr_methods($method)]} { 76c7991bdfSdan incr ::shmfault_ioerr_countdown -1 77c7991bdfSdan if { ($::shmfault_ioerr_countdown==0) 78c7991bdfSdan || ($::shmfault_ioerr_countdown<=0 && $::shmfault_ioerr_persist) 79c7991bdfSdan } { 80c7991bdfSdan return SQLITE_IOERR 81c7991bdfSdan } 82c7991bdfSdan } 83c7991bdfSdan return SQLITE_OK 84c7991bdfSdan} 85c7991bdfSdan 86*8f6097c2Sdan# Options are: 87*8f6097c2Sdan# 88*8f6097c2Sdan# -tclprep TCL 89*8f6097c2Sdan# -sqlprep SQL 90*8f6097c2Sdan# -sqlbody SQL 91*8f6097c2Sdan# 92c7991bdfSdanproc do_shmfault_test {name args} { 93*8f6097c2Sdan 94*8f6097c2Sdan set A(-tclprep) "sqlite3 db test.db -vfs shmfault" 95*8f6097c2Sdan set A(-sqlprep) "" 96*8f6097c2Sdan set A(-sqlbody) "" 97*8f6097c2Sdan set A(-methods) [list xShmGet xShmOpen xShmSize] 98c7991bdfSdan array set A $args 99c7991bdfSdan 100c7991bdfSdan # Create a VFS to use: 101c7991bdfSdan testvfs shmfault shmfault_vfs_cb 102c7991bdfSdan 103*8f6097c2Sdan unset -nocomplain ::shmfault_ioerr_methods 104*8f6097c2Sdan foreach m $A(-methods) { set ::shmfault_ioerr_methods($m) 1 } 105*8f6097c2Sdan 106c7991bdfSdan foreach mode {transient persistent} { 107c7991bdfSdan set ::shmfault_ioerr_persist [expr {$mode == "persistent"}] 108*8f6097c2Sdan 109c7991bdfSdan for {set nDelay 1} {$nDelay < 10000} {incr nDelay} { 110c7991bdfSdan 111c7991bdfSdan file delete -force test.db test.db-wal test.db-journal 112c7991bdfSdan 113*8f6097c2Sdan eval $A(-tclprep) 114*8f6097c2Sdan db eval $A(-sqlprep) 115*8f6097c2Sdan 116*8f6097c2Sdan set ::shmfault_ioerr_countdown $nDelay 117*8f6097c2Sdan set rc [catch { db eval $A(-sqlbody) } msg] 118c7991bdfSdan set hit_error [expr {$::shmfault_ioerr_countdown<=0}] 119c7991bdfSdan unset ::shmfault_ioerr_countdown 120*8f6097c2Sdan 121c7991bdfSdan catch { db close } 122c7991bdfSdan 123c7991bdfSdan do_test $name-$mode.$nDelay.1 [list set {} $hit_error] $rc 124c7991bdfSdan 125c7991bdfSdan if {$hit_error==0} break 126c7991bdfSdan } 127c7991bdfSdan } 128c7991bdfSdan 129c7991bdfSdan shmfault delete 130c7991bdfSdan} 131c7991bdfSdan 132*8f6097c2Sdan 133c7991bdfSdando_shmfault_test walfault-shm-1 -sqlbody { 134c7991bdfSdan PRAGMA journal_mode = WAL; 135c7991bdfSdan CREATE TABLE t1(a PRIMARY KEY, b); 136c7991bdfSdan INSERT INTO t1 VALUES('a', 'b'); 137c7991bdfSdan PRAGMA wal_checkpoint; 138c7991bdfSdan} 13976ed3bc0Sdan 140*8f6097c2Sdando_shmfault_test walfault-shm-2 -methods xShmSize -sqlprep { 141*8f6097c2Sdan PRAGMA page_size = 512; 142*8f6097c2Sdan PRAGMA journal_mode = WAL; 143*8f6097c2Sdan PRAGMA wal_autocheckpoint = 0; 144*8f6097c2Sdan} -sqlbody { 145*8f6097c2Sdan CREATE TABLE t1(x); 146*8f6097c2Sdan BEGIN; 147*8f6097c2Sdan INSERT INTO t1 VALUES(randomblob(400)); /* 1 */ 148*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2 */ 149*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4 */ 150*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8 */ 151*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16 */ 152*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 32 */ 153*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 64 */ 154*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 128 */ 155*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 256 */ 156*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 512 */ 157*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 1024 */ 158*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2048 */ 159*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4096 */ 160*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8192 */ 161*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16384 */ 162*8f6097c2Sdan COMMIT; 163*8f6097c2Sdan} 164*8f6097c2Sdan 165*8f6097c2Sdando_shmfault_test walfault-shm-3 -methods xShmSize -tclprep { 166*8f6097c2Sdan sqlite3 db test.db -vfs shmfault 167*8f6097c2Sdan unset -nocomplain ::shmfault_ioerr_countdown 168*8f6097c2Sdan db eval { 169*8f6097c2Sdan PRAGMA page_size = 512; 170*8f6097c2Sdan PRAGMA journal_mode = WAL; 171*8f6097c2Sdan PRAGMA wal_autocheckpoint = 0; 172*8f6097c2Sdan CREATE TABLE t1(x); 173*8f6097c2Sdan BEGIN; 174*8f6097c2Sdan INSERT INTO t1 VALUES(randomblob(400)); /* 1 */ 175*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2 */ 176*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4 */ 177*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8 */ 178*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16 */ 179*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 32 */ 180*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 64 */ 181*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 128 */ 182*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 256 */ 183*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 512 */ 184*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 1024 */ 185*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2048 */ 186*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4096 */ 187*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8192 */ 188*8f6097c2Sdan INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16384 */ 189*8f6097c2Sdan COMMIT; 190*8f6097c2Sdan } 191*8f6097c2Sdan 192*8f6097c2Sdan set ::shmfault_ioerr_countdown 1 193*8f6097c2Sdan set ::shmfault_ioerr_methods(xShmGet) 1 194*8f6097c2Sdan db close 195*8f6097c2Sdan unset ::shmfault_ioerr_methods(xShmGet) 196*8f6097c2Sdan if {[file exists test.db-wal]==0} {error "Failed to create WAL file!"} 197*8f6097c2Sdan 198*8f6097c2Sdan sqlite3 db test.db -vfs shmfault 199*8f6097c2Sdanbreakpoint 200*8f6097c2Sdan} -sqlbody { 201*8f6097c2Sdan SELECT count(*) FROM t1; 202*8f6097c2Sdan} 203*8f6097c2Sdan 20476ed3bc0Sdanfinish_test 205c7991bdfSdan 206