1b0ac3e3aSdan# 2010 June 15 2b0ac3e3aSdan# 3b0ac3e3aSdan# The author disclaims copyright to this source code. In place of 4b0ac3e3aSdan# a legal notice, here is a blessing: 5b0ac3e3aSdan# 6b0ac3e3aSdan# May you do good and not evil. 7b0ac3e3aSdan# May you find forgiveness for yourself and forgive others. 8b0ac3e3aSdan# May you share freely, never taking more than you give. 9b0ac3e3aSdan# 10b0ac3e3aSdan#*********************************************************************** 11b0ac3e3aSdan# 12b0ac3e3aSdan 13b0ac3e3aSdanset testdir [file dirname $argv0] 14b0ac3e3aSdansource $testdir/tester.tcl 15b0ac3e3aSdansource $testdir/lock_common.tcl 16b0ac3e3aSdansource $testdir/malloc_common.tcl 17b0ac3e3aSdan 18b3f4351fSdanif {[permutation] == "inmemory_journal"} { 19b3f4351fSdan finish_test 20b3f4351fSdan return 21b3f4351fSdan} 22b3f4351fSdan 23b2f20bfcSshanehif {$::tcl_platform(platform)=="windows"} { 24b2f20bfcSshaneh finish_test 25b2f20bfcSshaneh return 26b2f20bfcSshaneh} 27b2f20bfcSshaneh 28b0ac3e3aSdanset a_string_counter 1 29b0ac3e3aSdanproc a_string {n} { 30b0ac3e3aSdan global a_string_counter 31b0ac3e3aSdan incr a_string_counter 32b0ac3e3aSdan string range [string repeat "${a_string_counter}." $n] 1 $n 33b0ac3e3aSdan} 34b0ac3e3aSdandb func a_string a_string 35b0ac3e3aSdan 36b0ac3e3aSdan#------------------------------------------------------------------------- 37b0ac3e3aSdan# Test fault-injection while rolling back a hot-journal file. 38b0ac3e3aSdan# 39b0ac3e3aSdando_test pagerfault-1-pre1 { 40b0ac3e3aSdan execsql { 41b0ac3e3aSdan PRAGMA journal_mode = DELETE; 42b0ac3e3aSdan PRAGMA cache_size = 10; 43b0ac3e3aSdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 44b0ac3e3aSdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 45b0ac3e3aSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 46b0ac3e3aSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 47b0ac3e3aSdan BEGIN; 48b0ac3e3aSdan INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; 49b0ac3e3aSdan INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; 50b0ac3e3aSdan INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; 51b0ac3e3aSdan INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; 52b0ac3e3aSdan } 53b0ac3e3aSdan faultsim_save_and_close 54b0ac3e3aSdan} {} 55b0ac3e3aSdando_faultsim_test pagerfault-1 -prep { 56b0ac3e3aSdan faultsim_restore_and_reopen 57b0ac3e3aSdan} -body { 58b0ac3e3aSdan execsql { SELECT count(*) FROM t1 } 59b0ac3e3aSdan} -test { 60b0ac3e3aSdan faultsim_test_result {0 4} 61b0ac3e3aSdan faultsim_integrity_check 62b0ac3e3aSdan if {[db one { SELECT count(*) FROM t1 }] != 4} { 63b0ac3e3aSdan error "Database content appears incorrect" 64b0ac3e3aSdan } 65b0ac3e3aSdan} 66b0ac3e3aSdan 67b0ac3e3aSdan#------------------------------------------------------------------------- 68de4996e2Sdan# Test fault-injection while rolling back a hot-journal file with a 69de4996e2Sdan# page-size different from the current value stored on page 1 of the 70de4996e2Sdan# database file. 71de4996e2Sdan# 72de4996e2Sdando_test pagerfault-2-pre1 { 73de4996e2Sdan testvfs tv -default 1 74de4996e2Sdan tv filter xSync 75de4996e2Sdan tv script xSyncCb 76de4996e2Sdan proc xSyncCb {filename args} { 77de4996e2Sdan if {[string match *journal filename]==0} faultsim_save 78de4996e2Sdan } 79de4996e2Sdan faultsim_delete_and_reopen 80de4996e2Sdan execsql { 81de4996e2Sdan PRAGMA page_size = 4096; 82de4996e2Sdan BEGIN; 83de4996e2Sdan CREATE TABLE abc(a, b, c); 84de4996e2Sdan INSERT INTO abc VALUES('o', 't', 't'); 85de4996e2Sdan INSERT INTO abc VALUES('f', 'f', 's'); 86de4996e2Sdan INSERT INTO abc SELECT * FROM abc; -- 4 87de4996e2Sdan INSERT INTO abc SELECT * FROM abc; -- 8 88de4996e2Sdan INSERT INTO abc SELECT * FROM abc; -- 16 89de4996e2Sdan INSERT INTO abc SELECT * FROM abc; -- 32 90de4996e2Sdan INSERT INTO abc SELECT * FROM abc; -- 64 91de4996e2Sdan INSERT INTO abc SELECT * FROM abc; -- 128 92de4996e2Sdan INSERT INTO abc SELECT * FROM abc; -- 256 93de4996e2Sdan COMMIT; 94de4996e2Sdan PRAGMA page_size = 1024; 95de4996e2Sdan VACUUM; 96de4996e2Sdan } 97de4996e2Sdan db close 98de4996e2Sdan tv delete 99de4996e2Sdan} {} 100de4996e2Sdando_faultsim_test pagerfault-2 -prep { 101de4996e2Sdan faultsim_restore_and_reopen 102de4996e2Sdan} -body { 103de4996e2Sdan execsql { SELECT * FROM abc } 104de4996e2Sdan} -test { 105de4996e2Sdan set answer [split [string repeat "ottffs" 128] ""] 106de4996e2Sdan faultsim_test_result [list 0 $answer] 107de4996e2Sdan faultsim_integrity_check 108de4996e2Sdan set res [db eval { SELECT * FROM abc }] 109de4996e2Sdan if {$res != $answer} { error "Database content appears incorrect ($res)" } 110ec6ffc1aSdan} 111de4996e2Sdan 112de4996e2Sdan#------------------------------------------------------------------------- 113b0ac3e3aSdan# Test fault-injection while rolling back hot-journals that were created 114b0ac3e3aSdan# as part of a multi-file transaction. 115b0ac3e3aSdan# 116de4996e2Sdando_test pagerfault-3-pre1 { 117b0ac3e3aSdan testvfs tstvfs -default 1 118b0ac3e3aSdan tstvfs filter xDelete 119b0ac3e3aSdan tstvfs script xDeleteCallback 120b0ac3e3aSdan 121b0ac3e3aSdan proc xDeleteCallback {method file args} { 122b0ac3e3aSdan set file [file tail $file] 123b0ac3e3aSdan if { [string match *mj* $file] } { faultsim_save } 124b0ac3e3aSdan } 125b0ac3e3aSdan 126b0ac3e3aSdan faultsim_delete_and_reopen 127b0ac3e3aSdan db func a_string a_string 128b0ac3e3aSdan 129b0ac3e3aSdan execsql { 130b0ac3e3aSdan ATTACH 'test.db2' AS aux; 131b0ac3e3aSdan PRAGMA journal_mode = DELETE; 132b0ac3e3aSdan PRAGMA main.cache_size = 10; 133b0ac3e3aSdan PRAGMA aux.cache_size = 10; 134b0ac3e3aSdan 135b0ac3e3aSdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 136b0ac3e3aSdan CREATE TABLE aux.t2(a UNIQUE, b UNIQUE); 137b0ac3e3aSdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 138b0ac3e3aSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 139b0ac3e3aSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 140b0ac3e3aSdan INSERT INTO t2 SELECT * FROM t1; 141b0ac3e3aSdan 142b0ac3e3aSdan BEGIN; 143b0ac3e3aSdan INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; 144b0ac3e3aSdan INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; 145b0ac3e3aSdan INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; 146b0ac3e3aSdan INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; 147b0ac3e3aSdan REPLACE INTO t2 SELECT * FROM t1; 148b0ac3e3aSdan COMMIT; 149b0ac3e3aSdan } 150b0ac3e3aSdan 151b0ac3e3aSdan db close 152b0ac3e3aSdan tstvfs delete 153b0ac3e3aSdan} {} 154ec6ffc1aSdando_faultsim_test pagerfault-3 -prep { 155b0ac3e3aSdan faultsim_restore_and_reopen 156b0ac3e3aSdan} -body { 157b0ac3e3aSdan execsql { 158b0ac3e3aSdan ATTACH 'test.db2' AS aux; 159b0ac3e3aSdan SELECT count(*) FROM t2; 160b0ac3e3aSdan SELECT count(*) FROM t1; 161b0ac3e3aSdan } 162b0ac3e3aSdan} -test { 163b0ac3e3aSdan faultsim_test_result {0 {4 4}} {1 {unable to open database: test.db2}} 164b0ac3e3aSdan faultsim_integrity_check 165b0ac3e3aSdan catchsql { ATTACH 'test.db2' AS aux } 166b0ac3e3aSdan if {[db one { SELECT count(*) FROM t1 }] != 4 167b0ac3e3aSdan || [db one { SELECT count(*) FROM t2 }] != 4 168b0ac3e3aSdan } { 169b0ac3e3aSdan error "Database content appears incorrect" 170b0ac3e3aSdan } 171b0ac3e3aSdan} 172b0ac3e3aSdan 173de4996e2Sdan#------------------------------------------------------------------------- 174de4996e2Sdan# Test fault-injection as part of a vanilla, no-transaction, INSERT 175de4996e2Sdan# statement. 176de4996e2Sdan# 177de4996e2Sdando_faultsim_test pagerfault-4 -prep { 178de4996e2Sdan faultsim_delete_and_reopen 179de4996e2Sdan} -body { 180de4996e2Sdan execsql { 181de4996e2Sdan CREATE TABLE x(y); 182de4996e2Sdan INSERT INTO x VALUES('z'); 183de4996e2Sdan SELECT * FROM x; 184de4996e2Sdan } 185de4996e2Sdan} -test { 186de4996e2Sdan faultsim_test_result {0 z} 187de4996e2Sdan faultsim_integrity_check 188de4996e2Sdan} 189de4996e2Sdan 190de4996e2Sdan#------------------------------------------------------------------------- 191de4996e2Sdan# Test fault-injection as part of a commit when using journal_mode=PERSIST. 192146ed78bSdan# Three different cases: 193146ed78bSdan# 194146ed78bSdan# pagerfault-5.1: With no journal_size_limit configured. 195146ed78bSdan# pagerfault-5.2: With a journal_size_limit configured. 196146ed78bSdan# pagerfault-5.4: Multi-file transaction. One connection has a 197146ed78bSdan# journal_size_limit of 0, the other has no limit. 198de4996e2Sdan# 199de4996e2Sdando_test pagerfault-5-pre1 { 200de4996e2Sdan faultsim_delete_and_reopen 201de4996e2Sdan db func a_string a_string 202de4996e2Sdan execsql { 203de4996e2Sdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 204de4996e2Sdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 205de4996e2Sdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 206de4996e2Sdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 207de4996e2Sdan } 208de4996e2Sdan faultsim_save_and_close 209de4996e2Sdan} {} 210de4996e2Sdando_faultsim_test pagerfault-5.1 -prep { 211de4996e2Sdan faultsim_restore_and_reopen 212de4996e2Sdan db func a_string a_string 213de4996e2Sdan execsql { PRAGMA journal_mode = PERSIST } 214de4996e2Sdan} -body { 215de4996e2Sdan execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } 216de4996e2Sdan} -test { 217de4996e2Sdan faultsim_test_result {0 {}} 218de4996e2Sdan faultsim_integrity_check 219de4996e2Sdan} 220de4996e2Sdando_faultsim_test pagerfault-5.2 -prep { 221de4996e2Sdan faultsim_restore_and_reopen 222de4996e2Sdan db func a_string a_string 223de4996e2Sdan execsql { 224de4996e2Sdan PRAGMA journal_mode = PERSIST; 225de4996e2Sdan PRAGMA journal_size_limit = 2048; 226de4996e2Sdan } 227de4996e2Sdan} -body { 228de4996e2Sdan execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } 229de4996e2Sdan} -test { 230de4996e2Sdan faultsim_test_result {0 {}} 231de4996e2Sdan faultsim_integrity_check 232de4996e2Sdan} 233ec6ffc1aSdando_faultsim_test pagerfault-5.3 -faults oom-transient -prep { 234de4996e2Sdan faultsim_restore_and_reopen 235de4996e2Sdan db func a_string a_string 236fda06befSmistachkin forcedelete test2.db test2.db-journal test2.db-wal 237de4996e2Sdan execsql { 238de4996e2Sdan PRAGMA journal_mode = PERSIST; 239de4996e2Sdan ATTACH 'test2.db' AS aux; 240de4996e2Sdan PRAGMA aux.journal_mode = PERSIST; 241de4996e2Sdan PRAGMA aux.journal_size_limit = 0; 242de4996e2Sdan } 243de4996e2Sdan} -body { 244de4996e2Sdan execsql { 245de4996e2Sdan BEGIN; 246de4996e2Sdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 247de4996e2Sdan CREATE TABLE aux.t2 AS SELECT * FROM t1; 248de4996e2Sdan COMMIT; 249de4996e2Sdan } 250de4996e2Sdan} -test { 251de4996e2Sdan faultsim_test_result {0 {}} 252ec6ffc1aSdan 253f43d7fceSdan catchsql { COMMIT } 254f43d7fceSdan catchsql { ROLLBACK } 255f43d7fceSdan 256f43d7fceSdan faultsim_integrity_check 257ec6ffc1aSdan set res "" 258ec6ffc1aSdan set rc [catch { set res [db one { PRAGMA aux.integrity_check }] }] 259ec6ffc1aSdan if {$rc!=0 || $res != "ok"} {error "integrity-check problem:$rc $res"} 260de4996e2Sdan} 261de4996e2Sdan 262153eda0aSdan#------------------------------------------------------------------------- 263153eda0aSdan# Test fault-injection as part of a commit when using 264153eda0aSdan# journal_mode=TRUNCATE. 265153eda0aSdan# 266153eda0aSdando_test pagerfault-6-pre1 { 267153eda0aSdan faultsim_delete_and_reopen 268153eda0aSdan db func a_string a_string 269153eda0aSdan execsql { 270153eda0aSdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 271153eda0aSdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 272153eda0aSdan } 273153eda0aSdan faultsim_save_and_close 274153eda0aSdan} {} 275f9b4419dSdan 276153eda0aSdando_faultsim_test pagerfault-6.1 -prep { 277153eda0aSdan faultsim_restore_and_reopen 278153eda0aSdan db func a_string a_string 279153eda0aSdan execsql { PRAGMA journal_mode = TRUNCATE } 280153eda0aSdan} -body { 281153eda0aSdan execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } 282f9b4419dSdan execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } 283f9b4419dSdan} -test { 284f9b4419dSdan faultsim_test_result {0 {}} 285f9b4419dSdan faultsim_integrity_check 286f9b4419dSdan} 287f9b4419dSdan 288f9b4419dSdan# The unix vfs xAccess() method considers a file zero bytes in size to 289f9b4419dSdan# "not exist". This proc overrides that behaviour so that a zero length 290f9b4419dSdan# file is considered to exist. 291f9b4419dSdan# 292f9b4419dSdanproc xAccess {method filename op args} { 293f9b4419dSdan if {$op != "SQLITE_ACCESS_EXISTS"} { return "" } 294f9b4419dSdan return [file exists $filename] 295f9b4419dSdan} 296f9b4419dSdando_faultsim_test pagerfault-6.2 -faults cantopen-* -prep { 297f9b4419dSdan shmfault filter xAccess 298f9b4419dSdan shmfault script xAccess 299f9b4419dSdan 300f9b4419dSdan faultsim_restore_and_reopen 301f9b4419dSdan db func a_string a_string 302f9b4419dSdan execsql { PRAGMA journal_mode = TRUNCATE } 303f9b4419dSdan} -body { 304f9b4419dSdan execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } 305f9b4419dSdan execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 } 306153eda0aSdan} -test { 307153eda0aSdan faultsim_test_result {0 {}} 308153eda0aSdan faultsim_integrity_check 309153eda0aSdan} 310153eda0aSdan 311146ed78bSdan# The following was an attempt to get a bitvec malloc to fail. Didn't work. 312146ed78bSdan# 313146ed78bSdan# do_test pagerfault-6-pre1 { 314146ed78bSdan# faultsim_delete_and_reopen 315146ed78bSdan# execsql { 316146ed78bSdan# CREATE TABLE t1(x, y, UNIQUE(x, y)); 317146ed78bSdan# INSERT INTO t1 VALUES(1, randomblob(1501)); 318146ed78bSdan# INSERT INTO t1 VALUES(2, randomblob(1502)); 319146ed78bSdan# INSERT INTO t1 VALUES(3, randomblob(1503)); 320146ed78bSdan# INSERT INTO t1 VALUES(4, randomblob(1504)); 321146ed78bSdan# INSERT INTO t1 322146ed78bSdan# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; 323146ed78bSdan# INSERT INTO t1 324146ed78bSdan# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; 325146ed78bSdan# INSERT INTO t1 326146ed78bSdan# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; 327146ed78bSdan# INSERT INTO t1 328146ed78bSdan# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1; 329146ed78bSdan# } 330146ed78bSdan# faultsim_save_and_close 331146ed78bSdan# } {} 332146ed78bSdan# do_faultsim_test pagerfault-6 -prep { 333146ed78bSdan# faultsim_restore_and_reopen 334146ed78bSdan# } -body { 335146ed78bSdan# execsql { 336146ed78bSdan# BEGIN; 337146ed78bSdan# UPDATE t1 SET x=x+4 WHERE x=1; 338146ed78bSdan# SAVEPOINT one; 339146ed78bSdan# UPDATE t1 SET x=x+4 WHERE x=2; 340146ed78bSdan# SAVEPOINT three; 341146ed78bSdan# UPDATE t1 SET x=x+4 WHERE x=3; 342146ed78bSdan# SAVEPOINT four; 343146ed78bSdan# UPDATE t1 SET x=x+4 WHERE x=4; 344146ed78bSdan# RELEASE three; 345146ed78bSdan# COMMIT; 346146ed78bSdan# SELECT DISTINCT x FROM t1; 347146ed78bSdan# } 348146ed78bSdan# } -test { 349146ed78bSdan# faultsim_test_result {0 {5 6 7 8}} 350146ed78bSdan# faultsim_integrity_check 351146ed78bSdan# } 352346e4267Sdan# 353dca321aeSdan 354dca321aeSdan# This is designed to provoke a special case in the pager code: 355dca321aeSdan# 356dca321aeSdan# If an error (specifically, a FULL or IOERR error) occurs while writing a 357dca321aeSdan# dirty page to the file-system in order to free up memory, the pager enters 358dca321aeSdan# the "error state". An IO error causes SQLite to roll back the current 359dca321aeSdan# transaction (exiting the error state). A FULL error, however, may only 360dca321aeSdan# rollback the current statement. 361dca321aeSdan# 362dca321aeSdan# This block tests that nothing goes wrong if a FULL error occurs while 363dca321aeSdan# writing a dirty page out to free memory from within a statement that has 364dca321aeSdan# opened a statement transaction. 365dca321aeSdan# 366346e4267Sdando_test pagerfault-7-pre1 { 367346e4267Sdan faultsim_delete_and_reopen 368346e4267Sdan execsql { 369346e4267Sdan CREATE TABLE t2(a INTEGER PRIMARY KEY, b); 370346e4267Sdan BEGIN; 371346e4267Sdan INSERT INTO t2 VALUES(NULL, randomblob(1500)); 372346e4267Sdan INSERT INTO t2 VALUES(NULL, randomblob(1500)); 373346e4267Sdan INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 4 374346e4267Sdan INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 8 375346e4267Sdan INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 16 376346e4267Sdan INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 32 377346e4267Sdan INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 64 378346e4267Sdan COMMIT; 379346e4267Sdan CREATE TABLE t1(a PRIMARY KEY, b); 380346e4267Sdan INSERT INTO t1 SELECT * FROM t2; 381346e4267Sdan DROP TABLE t2; 382346e4267Sdan } 383346e4267Sdan faultsim_save_and_close 384346e4267Sdan} {} 385ec6ffc1aSdando_faultsim_test pagerfault-7 -prep { 386346e4267Sdan faultsim_restore_and_reopen 387346e4267Sdan execsql { 388346e4267Sdan PRAGMA cache_size = 10; 389346e4267Sdan BEGIN; 390346e4267Sdan UPDATE t1 SET b = randomblob(1500); 391346e4267Sdan } 392346e4267Sdan} -body { 393346e4267Sdan execsql { UPDATE t1 SET a = 65, b = randomblob(1500) WHERE (a+1)>200 } 394346e4267Sdan execsql COMMIT 395346e4267Sdan} -test { 396346e4267Sdan faultsim_test_result {0 {}} 397346e4267Sdan faultsim_integrity_check 398346e4267Sdan} 399146ed78bSdan 400dca321aeSdando_test pagerfault-8-pre1 { 401dca321aeSdan faultsim_delete_and_reopen 402dca321aeSdan execsql { 403dca321aeSdan PRAGMA auto_vacuum = 1; 404dca321aeSdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 405dca321aeSdan BEGIN; 406dca321aeSdan INSERT INTO t1 VALUES(NULL, randomblob(1500)); 407dca321aeSdan INSERT INTO t1 VALUES(NULL, randomblob(1500)); 408dca321aeSdan INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 4 409dca321aeSdan INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 8 410dca321aeSdan INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 16 411dca321aeSdan INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 32 412dca321aeSdan INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 64 413dca321aeSdan COMMIT; 414dca321aeSdan } 415dca321aeSdan faultsim_save_and_close 416dca321aeSdan set filesize [file size test.db] 417dca321aeSdan set {} {} 418dca321aeSdan} {} 419dca321aeSdando_test pagerfault-8-pre2 { 420dca321aeSdan faultsim_restore_and_reopen 421dca321aeSdan execsql { DELETE FROM t1 WHERE a>32 } 422dca321aeSdan expr {[file size test.db] < $filesize} 423dca321aeSdan} {1} 424dca321aeSdando_faultsim_test pagerfault-8 -prep { 425dca321aeSdan faultsim_restore_and_reopen 426dca321aeSdan execsql { 427dca321aeSdan BEGIN; 428dca321aeSdan DELETE FROM t1 WHERE a>32; 429dca321aeSdan } 430dca321aeSdan} -body { 431dca321aeSdan execsql COMMIT 432dca321aeSdan} -test { 433dca321aeSdan faultsim_test_result {0 {}} 434dca321aeSdan faultsim_integrity_check 435dca321aeSdan} 436dca321aeSdan 437273f3f0dSdan#------------------------------------------------------------------------- 438273f3f0dSdan# This test case is specially designed so that during a savepoint 439273f3f0dSdan# rollback, a new cache entry must be allocated (see comments surrounding 440273f3f0dSdan# the call to sqlite3PagerAcquire() from within pager_playback_one_page() 441273f3f0dSdan# for details). Test the effects of injecting an OOM at this point. 442273f3f0dSdan# 4430a6052ecSdando_test pagerfault-9-pre1 { 4440a6052ecSdan faultsim_delete_and_reopen 4450a6052ecSdan execsql { 4460a6052ecSdan PRAGMA auto_vacuum = incremental; 4470a6052ecSdan CREATE TABLE t1(x); 4480a6052ecSdan CREATE TABLE t2(y); 4490a6052ecSdan CREATE TABLE t3(z); 4500a6052ecSdan 4510a6052ecSdan INSERT INTO t1 VALUES(randomblob(900)); 4520a6052ecSdan INSERT INTO t1 VALUES(randomblob(900)); 4530a6052ecSdan DELETE FROM t1; 4540a6052ecSdan } 4550a6052ecSdan faultsim_save_and_close 4560a6052ecSdan} {} 457273f3f0dSdando_faultsim_test pagerfault-9.1 -prep { 4580a6052ecSdan faultsim_restore_and_reopen 4590a6052ecSdan execsql { 4600a6052ecSdan BEGIN; 4610a6052ecSdan INSERT INTO t1 VALUES(randomblob(900)); 4620a6052ecSdan INSERT INTO t1 VALUES(randomblob(900)); 4630a6052ecSdan DROP TABLE t3; 4640a6052ecSdan DROP TABLE t2; 4650a6052ecSdan SAVEPOINT abc; 4660a6052ecSdan PRAGMA incremental_vacuum; 4670a6052ecSdan } 4680a6052ecSdan} -body { 4690a6052ecSdan execsql { 4700a6052ecSdan ROLLBACK TO abc; 4710a6052ecSdan COMMIT; 4720a6052ecSdan PRAGMA freelist_count 4730a6052ecSdan } 4740a6052ecSdan} -test { 4750a6052ecSdan faultsim_test_result {0 2} 4760a6052ecSdan faultsim_integrity_check 4770a6052ecSdan 4780a6052ecSdan set sl [db one { SELECT COALESCE(sum(length(x)), 'null') FROM t1 }] 4790a6052ecSdan if {$sl!="null" && $sl!=1800} { 4800a6052ecSdan error "Content looks no good... ($sl)" 4810a6052ecSdan } 4820a6052ecSdan} 4830a6052ecSdan 484273f3f0dSdan#------------------------------------------------------------------------- 485273f3f0dSdan# Test fault injection with a temporary database file. 486273f3f0dSdan# 487c8ce3972Sdanforeach v {a b} { 488c8ce3972Sdan do_faultsim_test pagerfault-10$v -prep { 489273f3f0dSdan sqlite3 db "" 490273f3f0dSdan db func a_string a_string; 491273f3f0dSdan execsql { 492273f3f0dSdan PRAGMA cache_size = 10; 493273f3f0dSdan BEGIN; 494273f3f0dSdan CREATE TABLE xx(a, b, UNIQUE(a, b)); 495273f3f0dSdan INSERT INTO xx VALUES(a_string(200), a_string(200)); 496273f3f0dSdan INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; 497273f3f0dSdan INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; 498273f3f0dSdan INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; 499273f3f0dSdan INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx; 500273f3f0dSdan COMMIT; 501273f3f0dSdan } 502273f3f0dSdan } -body { 503273f3f0dSdan execsql { UPDATE xx SET a = a_string(300) } 504273f3f0dSdan } -test { 505273f3f0dSdan faultsim_test_result {0 {}} 506c8ce3972Sdan if {$::v == "b"} { execsql { PRAGMA journal_mode = TRUNCATE } } 507273f3f0dSdan faultsim_integrity_check 508273f3f0dSdan faultsim_integrity_check 509273f3f0dSdan } 510c8ce3972Sdan} 511273f3f0dSdan 512273f3f0dSdan#------------------------------------------------------------------------- 513273f3f0dSdan# Test fault injection with transaction savepoints (savepoints created 514273f3f0dSdan# when a SAVEPOINT command is executed outside of any other savepoint 515273f3f0dSdan# or transaction context). 516273f3f0dSdan# 517273f3f0dSdando_test pagerfault-9-pre1 { 518273f3f0dSdan faultsim_delete_and_reopen 519273f3f0dSdan db func a_string a_string; 520273f3f0dSdan execsql { 521273f3f0dSdan PRAGMA auto_vacuum = on; 522273f3f0dSdan CREATE TABLE t1(x UNIQUE); 523273f3f0dSdan CREATE TABLE t2(y UNIQUE); 524273f3f0dSdan CREATE TABLE t3(z UNIQUE); 525273f3f0dSdan BEGIN; 526273f3f0dSdan INSERT INTO t1 VALUES(a_string(202)); 527273f3f0dSdan INSERT INTO t2 VALUES(a_string(203)); 528273f3f0dSdan INSERT INTO t3 VALUES(a_string(204)); 529273f3f0dSdan INSERT INTO t1 SELECT a_string(202) FROM t1; 530273f3f0dSdan INSERT INTO t1 SELECT a_string(203) FROM t1; 531273f3f0dSdan INSERT INTO t1 SELECT a_string(204) FROM t1; 532273f3f0dSdan INSERT INTO t1 SELECT a_string(205) FROM t1; 533273f3f0dSdan INSERT INTO t2 SELECT a_string(length(x)) FROM t1; 534273f3f0dSdan INSERT INTO t3 SELECT a_string(length(x)) FROM t1; 535273f3f0dSdan COMMIT; 536273f3f0dSdan } 537273f3f0dSdan faultsim_save_and_close 538273f3f0dSdan} {} 539273f3f0dSdando_faultsim_test pagerfault-11 -prep { 540273f3f0dSdan faultsim_restore_and_reopen 541273f3f0dSdan execsql { PRAGMA cache_size = 10 } 542273f3f0dSdan} -body { 543273f3f0dSdan execsql { 544273f3f0dSdan SAVEPOINT trans; 545273f3f0dSdan UPDATE t2 SET y = y||'2'; 546273f3f0dSdan INSERT INTO t3 SELECT * FROM t2; 547273f3f0dSdan DELETE FROM t1; 548273f3f0dSdan ROLLBACK TO trans; 549273f3f0dSdan UPDATE t1 SET x = x||'3'; 550273f3f0dSdan INSERT INTO t2 SELECT * FROM t1; 551273f3f0dSdan DELETE FROM t3; 552273f3f0dSdan RELEASE trans; 553273f3f0dSdan } 554273f3f0dSdan} -test { 555273f3f0dSdan faultsim_test_result {0 {}} 556273f3f0dSdan faultsim_integrity_check 557273f3f0dSdan} 558273f3f0dSdan 559c396d4afSdan 560c8ce3972Sdan#------------------------------------------------------------------------- 561c8ce3972Sdan# Test fault injection when writing to a database file that resides on 562c8ce3972Sdan# a file-system with a sector-size larger than the database page-size. 563c8ce3972Sdan# 564d353331aSdando_test pagerfault-12-pre1 { 565d353331aSdan testvfs ss_layer -default 1 566d353331aSdan ss_layer sectorsize 4096 567d353331aSdan faultsim_delete_and_reopen 568d353331aSdan db func a_string a_string; 569d353331aSdan 570d353331aSdan execsql { 571d353331aSdan PRAGMA page_size = 1024; 572d353331aSdan PRAGMA journal_mode = PERSIST; 573d353331aSdan PRAGMA cache_size = 10; 574d353331aSdan BEGIN; 575d353331aSdan CREATE TABLE t1(x, y UNIQUE); 576d353331aSdan INSERT INTO t1 VALUES(a_string(333), a_string(444)); 577d353331aSdan INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1; 578d353331aSdan INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1; 579d353331aSdan INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1; 580d353331aSdan INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1; 581d353331aSdan INSERT INTO t1 SELECT a_string(44), a_string(55) FROM t1 LIMIT 13; 582d353331aSdan COMMIT; 583d353331aSdan } 584d353331aSdan faultsim_save_and_close 585d353331aSdan} {} 586c396d4afSdan 587c396d4afSdando_faultsim_test pagerfault-12a -prep { 588d353331aSdan faultsim_restore_and_reopen 589d353331aSdan execsql { PRAGMA cache_size = 10 } 590d353331aSdan db func a_string a_string; 591d353331aSdan} -body { 592d353331aSdan execsql { 593d353331aSdan UPDATE t1 SET x = a_string(length(x)), y = a_string(length(y)); 594d353331aSdan } 595d353331aSdan} -test { 596d353331aSdan faultsim_test_result {0 {}} 597d353331aSdan faultsim_integrity_check 598d353331aSdan} 599d353331aSdan 600c396d4afSdando_test pagerfault-12-pre2 { 601c396d4afSdan faultsim_restore_and_reopen 602c396d4afSdan execsql { 603c396d4afSdan CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 10; 604c396d4afSdan } 605c396d4afSdan faultsim_save_and_close 606c396d4afSdan} {} 607c396d4afSdando_faultsim_test pagerfault-12b -prep { 608c396d4afSdan faultsim_restore_and_reopen 609c396d4afSdan db func a_string a_string; 610c396d4afSdan execsql { SELECT * FROM t1 } 611c396d4afSdan} -body { 612c396d4afSdan set sql(1) { UPDATE t2 SET x = a_string(280) } 613c396d4afSdan set sql(2) { UPDATE t1 SET x = a_string(280) WHERE rowid = 5 } 614c396d4afSdan 615c396d4afSdan db eval { SELECT rowid FROM t1 LIMIT 2 } { db eval $sql($rowid) } 616c396d4afSdan 617c396d4afSdan} -test { 618c396d4afSdan faultsim_test_result {0 {}} 619c396d4afSdan faultsim_integrity_check 620c396d4afSdan} 621c396d4afSdan 622c396d4afSdancatch { db close } 623c396d4afSdanss_layer delete 624c396d4afSdan 625d353331aSdan 626c8ce3972Sdan#------------------------------------------------------------------------- 627ba3cbf3dSdan# Test fault injection when SQLite opens a database where the size of the 628ba3cbf3dSdan# database file is zero bytes but the accompanying journal file is larger 629ba3cbf3dSdan# than that. In this scenario SQLite should delete the journal file 630ba3cbf3dSdan# without rolling it back, even if it is in all other respects a valid 631ba3cbf3dSdan# hot-journal file. 632c8ce3972Sdan# 633c8ce3972Sdando_test pagerfault-13-pre1 { 634c8ce3972Sdan faultsim_delete_and_reopen 635c8ce3972Sdan db func a_string a_string; 636c8ce3972Sdan execsql { 637c8ce3972Sdan PRAGMA journal_mode = PERSIST; 638c8ce3972Sdan BEGIN; 639c8ce3972Sdan CREATE TABLE t1(x, y UNIQUE); 640c8ce3972Sdan INSERT INTO t1 VALUES(a_string(333), a_string(444)); 641c8ce3972Sdan COMMIT; 642c8ce3972Sdan } 643c8ce3972Sdan db close 644fda06befSmistachkin forcedelete test.db 645c8ce3972Sdan faultsim_save 646c8ce3972Sdan} {} 647c8ce3972Sdando_faultsim_test pagerfault-13 -prep { 648c8ce3972Sdan faultsim_restore_and_reopen 649c8ce3972Sdan} -body { 650c8ce3972Sdan execsql { CREATE TABLE xx(a, b) } 651c8ce3972Sdan} -test { 652c8ce3972Sdan faultsim_test_result {0 {}} 653c8ce3972Sdan} 654c8ce3972Sdan 655ba3cbf3dSdan#--------------------------------------------------------------------------- 656ba3cbf3dSdan# Test fault injection into a small backup operation. 657ba3cbf3dSdan# 658ba3cbf3dSdando_test pagerfault-14-pre1 { 659ba3cbf3dSdan faultsim_delete_and_reopen 660ba3cbf3dSdan db func a_string a_string; 661ba3cbf3dSdan execsql { 662ba3cbf3dSdan PRAGMA journal_mode = PERSIST; 663ba3cbf3dSdan ATTACH 'test.db2' AS two; 664ba3cbf3dSdan BEGIN; 665ba3cbf3dSdan CREATE TABLE t1(x, y UNIQUE); 666ba3cbf3dSdan CREATE TABLE two.t2(x, y UNIQUE); 667ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(333), a_string(444)); 668ba3cbf3dSdan INSERT INTO t2 VALUES(a_string(333), a_string(444)); 669ba3cbf3dSdan COMMIT; 670c8ce3972Sdan } 671ba3cbf3dSdan faultsim_save_and_close 672ba3cbf3dSdan} {} 6736b63ab47Sdan 6746b63ab47Sdando_faultsim_test pagerfault-14a -prep { 675ba3cbf3dSdan faultsim_restore_and_reopen 676ba3cbf3dSdan} -body { 677ba3cbf3dSdan if {[catch {db backup test.db2} msg]} { error [regsub {.*: } $msg {}] } 678ba3cbf3dSdan} -test { 679a690ff36Sdrh faultsim_test_result {0 {}} {1 {}} {1 {SQL logic error}} 680ba3cbf3dSdan} 681ab4f076eSdan 682fa2a4772Sdan# If TEMP_STORE is 2 or greater, then the database [db2] will be created 683fa2a4772Sdan# as an in-memory database. This test will not work in that case, as it 684fa2a4772Sdan# is not possible to change the page-size of an in-memory database. Even 685fa2a4772Sdan# using the backup API. 686fa2a4772Sdan# 6879bf01363Sdan# Update: It is no longer possible to change the page size of any temp 6889bf01363Sdan# database after it has been created. 6899bf01363Sdan# 6906b63ab47Sdando_faultsim_test pagerfault-14b -prep { 691caace926Sshaneh catch { db2 close } 6926b63ab47Sdan faultsim_restore_and_reopen 6936b63ab47Sdan sqlite3 db2 "" 6946b63ab47Sdan db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) } 6956b63ab47Sdan} -body { 6966b63ab47Sdan sqlite3_backup B db2 main db main 6976b63ab47Sdan B step 200 6986b63ab47Sdan set rc [B finish] 6996b63ab47Sdan if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR} 7006b63ab47Sdan if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] } 7016b63ab47Sdan set {} {} 7026b63ab47Sdan} -test { 7039bf01363Sdan faultsim_test_result {1 {attempt to write a readonly database}} \ 7049bf01363Sdan {1 {sqlite3_backup_init() failed}} 705fa2a4772Sdan} 706fa2a4772Sdan 707d0b0d4dcSdando_faultsim_test pagerfault-14c -prep { 708caace926Sshaneh catch { db2 close } 709d0b0d4dcSdan faultsim_restore_and_reopen 710d0b0d4dcSdan sqlite3 db2 test.db2 711d0b0d4dcSdan db2 eval { 712d0b0d4dcSdan PRAGMA synchronous = off; 713d0b0d4dcSdan PRAGMA page_size = 4096; 714d0b0d4dcSdan CREATE TABLE xx(a); 715d0b0d4dcSdan } 716d0b0d4dcSdan} -body { 717d0b0d4dcSdan sqlite3_backup B db2 main db main 718d0b0d4dcSdan B step 200 719d0b0d4dcSdan set rc [B finish] 720d0b0d4dcSdan if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR} 721d0b0d4dcSdan if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] } 722d0b0d4dcSdan set {} {} 723d0b0d4dcSdan} -test { 724ab4f076eSdan faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}} 725d0b0d4dcSdan} 726ba3cbf3dSdan 727ba3cbf3dSdando_test pagerfault-15-pre1 { 728ba3cbf3dSdan faultsim_delete_and_reopen 729ba3cbf3dSdan db func a_string a_string; 730ba3cbf3dSdan execsql { 731ba3cbf3dSdan BEGIN; 732ba3cbf3dSdan CREATE TABLE t1(x, y UNIQUE); 733ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(11), a_string(22)); 734ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(11), a_string(22)); 735ba3cbf3dSdan COMMIT; 736ba3cbf3dSdan } 737ba3cbf3dSdan faultsim_save_and_close 738ba3cbf3dSdan} {} 739ba3cbf3dSdando_faultsim_test pagerfault-15 -prep { 740ba3cbf3dSdan faultsim_restore_and_reopen 741ba3cbf3dSdan db func a_string a_string; 742ba3cbf3dSdan} -body { 743ba3cbf3dSdan db eval { SELECT * FROM t1 LIMIT 1 } { 744ba3cbf3dSdan execsql { 745ba3cbf3dSdan BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT; 746ba3cbf3dSdan BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT; 747ba3cbf3dSdan } 748ba3cbf3dSdan } 749ba3cbf3dSdan} -test { 750ba3cbf3dSdan faultsim_test_result {0 {}} 751ba3cbf3dSdan faultsim_integrity_check 752ba3cbf3dSdan} 753ba3cbf3dSdan 754ba3cbf3dSdan 755ba3cbf3dSdando_test pagerfault-16-pre1 { 756ba3cbf3dSdan faultsim_delete_and_reopen 757ba3cbf3dSdan execsql { CREATE TABLE t1(x, y UNIQUE) } 758ba3cbf3dSdan faultsim_save_and_close 759ba3cbf3dSdan} {} 760ba3cbf3dSdando_faultsim_test pagerfault-16 -prep { 761ba3cbf3dSdan faultsim_restore_and_reopen 762ba3cbf3dSdan} -body { 763ba3cbf3dSdan execsql { 764ba3cbf3dSdan PRAGMA locking_mode = exclusive; 765ba3cbf3dSdan PRAGMA journal_mode = wal; 766ba3cbf3dSdan INSERT INTO t1 VALUES(1, 2); 767ba3cbf3dSdan INSERT INTO t1 VALUES(3, 4); 768ba3cbf3dSdan PRAGMA journal_mode = delete; 769ba3cbf3dSdan INSERT INTO t1 VALUES(4, 5); 770ba3cbf3dSdan PRAGMA journal_mode = wal; 771ba3cbf3dSdan INSERT INTO t1 VALUES(6, 7); 772ba3cbf3dSdan PRAGMA journal_mode = persist; 773ba3cbf3dSdan INSERT INTO t1 VALUES(8, 9); 774ba3cbf3dSdan } 775ba3cbf3dSdan} -test { 776ba3cbf3dSdan faultsim_test_result {0 {exclusive wal delete wal persist}} 777ba3cbf3dSdan faultsim_integrity_check 778ba3cbf3dSdan} 779ba3cbf3dSdan 780c8ce3972Sdan 78189ccf448Sdan#------------------------------------------------------------------------- 78289ccf448Sdan# Test fault injection while changing into and out of WAL mode. 78389ccf448Sdan# 78489ccf448Sdando_test pagerfault-17-pre1 { 78589ccf448Sdan faultsim_delete_and_reopen 78689ccf448Sdan execsql { 78789ccf448Sdan CREATE TABLE t1(a PRIMARY KEY, b); 78889ccf448Sdan INSERT INTO t1 VALUES(1862, 'Botha'); 78989ccf448Sdan INSERT INTO t1 VALUES(1870, 'Smuts'); 79089ccf448Sdan INSERT INTO t1 VALUES(1866, 'Hertzog'); 79189ccf448Sdan } 79289ccf448Sdan faultsim_save_and_close 79389ccf448Sdan} {} 79489ccf448Sdando_faultsim_test pagerfault-17a -prep { 79589ccf448Sdan faultsim_restore_and_reopen 79689ccf448Sdan} -body { 79789ccf448Sdan execsql { 79889ccf448Sdan PRAGMA journal_mode = wal; 79989ccf448Sdan PRAGMA journal_mode = delete; 80089ccf448Sdan } 80189ccf448Sdan} -test { 80289ccf448Sdan faultsim_test_result {0 {wal delete}} 80389ccf448Sdan faultsim_integrity_check 80489ccf448Sdan} 80589ccf448Sdando_faultsim_test pagerfault-17b -prep { 80689ccf448Sdan faultsim_restore_and_reopen 80789ccf448Sdan execsql { PRAGMA synchronous = OFF } 80889ccf448Sdan} -body { 80989ccf448Sdan execsql { 81089ccf448Sdan PRAGMA journal_mode = wal; 81189ccf448Sdan INSERT INTO t1 VALUES(22, 'Clarke'); 81289ccf448Sdan PRAGMA journal_mode = delete; 81389ccf448Sdan } 81489ccf448Sdan} -test { 81589ccf448Sdan faultsim_test_result {0 {wal delete}} 81689ccf448Sdan faultsim_integrity_check 81789ccf448Sdan} 81889ccf448Sdando_faultsim_test pagerfault-17c -prep { 81989ccf448Sdan faultsim_restore_and_reopen 82089ccf448Sdan execsql { 82189ccf448Sdan PRAGMA locking_mode = exclusive; 82289ccf448Sdan PRAGMA journal_mode = wal; 82389ccf448Sdan } 82489ccf448Sdan} -body { 82589ccf448Sdan execsql { PRAGMA journal_mode = delete } 82689ccf448Sdan} -test { 82789ccf448Sdan faultsim_test_result {0 delete} 82889ccf448Sdan faultsim_integrity_check 82989ccf448Sdan} 83089ccf448Sdando_faultsim_test pagerfault-17d -prep { 831caace926Sshaneh catch { db2 close } 83289ccf448Sdan faultsim_restore_and_reopen 83389ccf448Sdan sqlite3 db2 test.db 83489ccf448Sdan execsql { PRAGMA journal_mode = delete } 83589ccf448Sdan execsql { PRAGMA journal_mode = wal } 83689ccf448Sdan execsql { INSERT INTO t1 VALUES(99, 'Bradman') } db2 83789ccf448Sdan} -body { 83889ccf448Sdan execsql { PRAGMA journal_mode = delete } 83989ccf448Sdan} -test { 84089ccf448Sdan faultsim_test_result {1 {database is locked}} 84189ccf448Sdan faultsim_integrity_check 84289ccf448Sdan} 84389ccf448Sdando_faultsim_test pagerfault-17e -prep { 844caace926Sshaneh catch { db2 close } 84589ccf448Sdan faultsim_restore_and_reopen 84689ccf448Sdan sqlite3 db2 test.db 84789ccf448Sdan execsql { PRAGMA journal_mode = delete } 84889ccf448Sdan execsql { PRAGMA journal_mode = wal } 84989ccf448Sdan set ::chan [launch_testfixture] 85089ccf448Sdan testfixture $::chan { 85189ccf448Sdan sqlite3 db test.db 85289ccf448Sdan db eval { INSERT INTO t1 VALUES(101, 'Latham') } 85389ccf448Sdan } 85489ccf448Sdan catch { testfixture $::chan sqlite_abort } 85589ccf448Sdan catch { close $::chan } 85689ccf448Sdan} -body { 85789ccf448Sdan execsql { PRAGMA journal_mode = delete } 85889ccf448Sdan} -test { 85989ccf448Sdan faultsim_test_result {0 delete} 86089ccf448Sdan faultsim_integrity_check 86189ccf448Sdan} 86289ccf448Sdan 86389ccf448Sdan#------------------------------------------------------------------------- 86489ccf448Sdan# Test fault-injection when changing from journal_mode=persist to 86589ccf448Sdan# journal_mode=delete (this involves deleting the journal file). 86689ccf448Sdan# 86789ccf448Sdando_test pagerfault-18-pre1 { 86889ccf448Sdan faultsim_delete_and_reopen 86989ccf448Sdan execsql { 87089ccf448Sdan CREATE TABLE qq(x); 87189ccf448Sdan INSERT INTO qq VALUES('Herbert'); 87289ccf448Sdan INSERT INTO qq VALUES('Macalister'); 87389ccf448Sdan INSERT INTO qq VALUES('Mackenzie'); 87489ccf448Sdan INSERT INTO qq VALUES('Lilley'); 87589ccf448Sdan INSERT INTO qq VALUES('Palmer'); 87689ccf448Sdan } 87789ccf448Sdan faultsim_save_and_close 87889ccf448Sdan} {} 87989ccf448Sdando_faultsim_test pagerfault-18 -prep { 88089ccf448Sdan faultsim_restore_and_reopen 88189ccf448Sdan execsql { 88289ccf448Sdan PRAGMA journal_mode = PERSIST; 88389ccf448Sdan INSERT INTO qq VALUES('Beatty'); 88489ccf448Sdan } 88589ccf448Sdan} -body { 88689ccf448Sdan execsql { PRAGMA journal_mode = delete } 88789ccf448Sdan} -test { 88889ccf448Sdan faultsim_test_result {0 delete} 88989ccf448Sdan faultsim_integrity_check 89089ccf448Sdan} 89189ccf448Sdan 89289ccf448Sdando_faultsim_test pagerfault-19a -prep { 89389ccf448Sdan sqlite3 db :memory: 89489ccf448Sdan db func a_string a_string 89589ccf448Sdan execsql { 89689ccf448Sdan PRAGMA auto_vacuum = FULL; 89789ccf448Sdan BEGIN; 89889ccf448Sdan CREATE TABLE t1(a, b); 89989ccf448Sdan INSERT INTO t1 VALUES(a_string(5000), a_string(6000)); 90089ccf448Sdan COMMIT; 90189ccf448Sdan } 90289ccf448Sdan} -body { 90389ccf448Sdan execsql { 90489ccf448Sdan CREATE TABLE t2(a, b); 90589ccf448Sdan INSERT INTO t2 SELECT * FROM t1; 90689ccf448Sdan DELETE FROM t1; 90789ccf448Sdan } 90889ccf448Sdan} -test { 90989ccf448Sdan faultsim_test_result {0 {}} 91089ccf448Sdan} 91189ccf448Sdan 91289ccf448Sdando_test pagerfault-19-pre1 { 91389ccf448Sdan faultsim_delete_and_reopen 91489ccf448Sdan execsql { 91589ccf448Sdan PRAGMA auto_vacuum = FULL; 91689ccf448Sdan CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); 91789ccf448Sdan CREATE TABLE t2(x); INSERT INTO t2 VALUES(2); 91889ccf448Sdan CREATE TABLE t3(x); INSERT INTO t3 VALUES(3); 91989ccf448Sdan CREATE TABLE t4(x); INSERT INTO t4 VALUES(4); 92089ccf448Sdan CREATE TABLE t5(x); INSERT INTO t5 VALUES(5); 92189ccf448Sdan CREATE TABLE t6(x); INSERT INTO t6 VALUES(6); 92289ccf448Sdan } 92389ccf448Sdan faultsim_save_and_close 92489ccf448Sdan} {} 92589ccf448Sdando_faultsim_test pagerfault-19b -prep { 92689ccf448Sdan faultsim_restore_and_reopen 92789ccf448Sdan} -body { 92889ccf448Sdan execsql { 92989ccf448Sdan BEGIN; 93089ccf448Sdan UPDATE t4 SET x = x+1; 93189ccf448Sdan UPDATE t6 SET x = x+1; 93289ccf448Sdan SAVEPOINT one; 93389ccf448Sdan UPDATE t3 SET x = x+1; 93489ccf448Sdan SAVEPOINT two; 93589ccf448Sdan DROP TABLE t2; 93689ccf448Sdan ROLLBACK TO one; 93789ccf448Sdan COMMIT; 93889ccf448Sdan SELECT * FROM t3; 93989ccf448Sdan SELECT * FROM t4; 94089ccf448Sdan SELECT * FROM t6; 94189ccf448Sdan } 94289ccf448Sdan} -test { 94389ccf448Sdan faultsim_test_result {0 {3 5 7}} 94489ccf448Sdan} 94589ccf448Sdan 946d0b0d4dcSdan#------------------------------------------------------------------------- 947d0b0d4dcSdan# This tests fault-injection in a special case in the auto-vacuum code. 948d0b0d4dcSdan# 94989ccf448Sdando_test pagerfault-20-pre1 { 95089ccf448Sdan faultsim_delete_and_reopen 95189ccf448Sdan execsql { 952d0b0d4dcSdan PRAGMA cache_size = 10; 953d0b0d4dcSdan PRAGMA auto_vacuum = FULL; 954d0b0d4dcSdan CREATE TABLE t0(a, b); 95589ccf448Sdan } 95689ccf448Sdan faultsim_save_and_close 95789ccf448Sdan} {} 95889ccf448Sdando_faultsim_test pagerfault-20 -prep { 95989ccf448Sdan faultsim_restore_and_reopen 96089ccf448Sdan} -body { 96189ccf448Sdan execsql { 96289ccf448Sdan BEGIN; 963d0b0d4dcSdan CREATE TABLE t1(a, b); 964d0b0d4dcSdan CREATE TABLE t2(a, b); 965d0b0d4dcSdan DROP TABLE t1; 96689ccf448Sdan COMMIT; 96789ccf448Sdan } 96889ccf448Sdan} -test { 96989ccf448Sdan faultsim_test_result {0 {}} 97089ccf448Sdan} 971273f3f0dSdan 972d0b0d4dcSdando_test pagerfault-21-pre1 { 973d0b0d4dcSdan faultsim_delete_and_reopen 974d0b0d4dcSdan execsql { 975d0b0d4dcSdan PRAGMA cache_size = 10; 976d0b0d4dcSdan CREATE TABLE t0(a PRIMARY KEY, b); 977d0b0d4dcSdan INSERT INTO t0 VALUES(1, 2); 978d0b0d4dcSdan } 979d0b0d4dcSdan faultsim_save_and_close 980d0b0d4dcSdan} {} 981d0b0d4dcSdando_faultsim_test pagerfault-21 -prep { 982d0b0d4dcSdan faultsim_restore_and_reopen 983d0b0d4dcSdan} -body { 984d0b0d4dcSdan db eval { SELECT * FROM t0 LIMIT 1 } { 985d0b0d4dcSdan db eval { INSERT INTO t0 SELECT a+1, b FROM t0 } 986d0b0d4dcSdan db eval { INSERT INTO t0 SELECT a+2, b FROM t0 } 987d0b0d4dcSdan } 988d0b0d4dcSdan} -test { 989d0b0d4dcSdan faultsim_test_result {0 {}} 990d0b0d4dcSdan} 991d0b0d4dcSdan 992d0b0d4dcSdan 9939d08d640Sdan#------------------------------------------------------------------------- 9949d08d640Sdan# Test fault-injection and rollback when the nReserve header value 9959d08d640Sdan# is non-zero. 9969d08d640Sdan# 9979d08d640Sdando_test pagerfault-21-pre1 { 9989d08d640Sdan faultsim_delete_and_reopen 9999d08d640Sdan execsql { 10009d08d640Sdan PRAGMA page_size = 1024; 10019d08d640Sdan PRAGMA journal_mode = WAL; 10029d08d640Sdan PRAGMA journal_mode = DELETE; 10039d08d640Sdan } 10049d08d640Sdan db close 10059d08d640Sdan hexio_write test.db 20 10 10069d08d640Sdan hexio_write test.db 105 03F0 10079d08d640Sdan sqlite3 db test.db 10089d08d640Sdan db func a_string a_string 10099d08d640Sdan execsql { 10109d08d640Sdan CREATE TABLE t0(a PRIMARY KEY, b UNIQUE); 10119d08d640Sdan INSERT INTO t0 VALUES(a_string(222), a_string(333)); 10129d08d640Sdan INSERT INTO t0 VALUES(a_string(223), a_string(334)); 10139d08d640Sdan INSERT INTO t0 VALUES(a_string(224), a_string(335)); 10149d08d640Sdan INSERT INTO t0 VALUES(a_string(225), a_string(336)); 10159d08d640Sdan } 10169d08d640Sdan faultsim_save_and_close 10179d08d640Sdan} {} 10189d08d640Sdan 10199d08d640Sdando_faultsim_test pagerfault-21 -prep { 10209d08d640Sdan faultsim_restore_and_reopen 10219d08d640Sdan} -body { 10229d08d640Sdan execsql { INSERT INTO t0 SELECT a||'x', b||'x' FROM t0 } 10239d08d640Sdan} -test { 10249d08d640Sdan faultsim_test_result {0 {}} 10259d08d640Sdan faultsim_integrity_check 10269d08d640Sdan} 10279d08d640Sdanifcapable crashtest { 10289d08d640Sdan faultsim_delete_and_reopen 10299d08d640Sdan execsql { 10309d08d640Sdan PRAGMA page_size = 1024; 10319d08d640Sdan PRAGMA journal_mode = WAL; 10329d08d640Sdan PRAGMA journal_mode = DELETE; 10339d08d640Sdan } 10349d08d640Sdan db close 10359d08d640Sdan hexio_write test.db 20 10 10369d08d640Sdan hexio_write test.db 105 03F0 10379d08d640Sdan 10389d08d640Sdan sqlite3 db test.db 10399d08d640Sdan db func a_string a_string 10409d08d640Sdan execsql { 10419d08d640Sdan CREATE TABLE t0(a PRIMARY KEY, b UNIQUE); 10429d08d640Sdan INSERT INTO t0 VALUES(a_string(222), a_string(333)); 10439d08d640Sdan INSERT INTO t0 VALUES(a_string(223), a_string(334)); 10449d08d640Sdan } 10459d08d640Sdan faultsim_save_and_close 10469d08d640Sdan 10479d08d640Sdan for {set iTest 1} {$iTest<50} {incr iTest} { 10489d08d640Sdan do_test pagerfault-21.crash.$iTest.1 { 10499d08d640Sdan crashsql -delay 1 -file test.db -seed $iTest { 10509d08d640Sdan BEGIN; 10519d08d640Sdan CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); 10529d08d640Sdan INSERT INTO t1 SELECT a, b FROM t0; 10539d08d640Sdan COMMIT; 10549d08d640Sdan } 10559d08d640Sdan } {1 {child process exited abnormally}} 10569d08d640Sdan do_test pagerfault-22.$iTest.2 { 10579d08d640Sdan sqlite3 db test.db 10589d08d640Sdan execsql { PRAGMA integrity_check } 10599d08d640Sdan } {ok} 10609d08d640Sdan db close 10619d08d640Sdan } 10629d08d640Sdan} 10639d08d640Sdan 106459257dc6Sdan 106559257dc6Sdan#------------------------------------------------------------------------- 106659257dc6Sdan# When a 3.7.0 client opens a write-transaction on a database file that 106759257dc6Sdan# has been appended to or truncated by a pre-370 client, it updates 106859257dc6Sdan# the db-size in the file header immediately. This test case provokes 106959257dc6Sdan# errors during that operation. 107059257dc6Sdan# 107159257dc6Sdando_test pagerfault-22-pre1 { 107259257dc6Sdan faultsim_delete_and_reopen 107359257dc6Sdan db func a_string a_string 107459257dc6Sdan execsql { 107559257dc6Sdan PRAGMA page_size = 1024; 107659257dc6Sdan PRAGMA auto_vacuum = 0; 107759257dc6Sdan CREATE TABLE t1(a); 107859257dc6Sdan CREATE INDEX i1 ON t1(a); 107959257dc6Sdan INSERT INTO t1 VALUES(a_string(3000)); 108059257dc6Sdan CREATE TABLE t2(a); 108159257dc6Sdan INSERT INTO t2 VALUES(1); 108259257dc6Sdan } 108359257dc6Sdan db close 108459257dc6Sdan sql36231 { INSERT INTO t1 VALUES(a_string(3000)) } 108559257dc6Sdan faultsim_save_and_close 108659257dc6Sdan} {} 108759257dc6Sdando_faultsim_test pagerfault-22 -prep { 108859257dc6Sdan faultsim_restore_and_reopen 108959257dc6Sdan} -body { 109059257dc6Sdan execsql { INSERT INTO t2 VALUES(2) } 109159257dc6Sdan execsql { SELECT * FROM t2 } 109259257dc6Sdan} -test { 109359257dc6Sdan faultsim_test_result {0 {1 2}} 109459257dc6Sdan faultsim_integrity_check 109559257dc6Sdan} 109622b328b2Sdan 109722b328b2Sdan#------------------------------------------------------------------------- 109822b328b2Sdan# Provoke an OOM error during a commit of multi-file transaction. One of 109922b328b2Sdan# the databases written during the transaction is an in-memory database. 110022b328b2Sdan# This test causes rollback of the in-memory database after CommitPhaseOne() 110122b328b2Sdan# has successfully returned. i.e. the series of calls for the aborted commit 110222b328b2Sdan# is: 110322b328b2Sdan# 110422b328b2Sdan# PagerCommitPhaseOne(<in-memory-db>) -> SQLITE_OK 110522b328b2Sdan# PagerCommitPhaseOne(<file-db>) -> SQLITE_IOERR 110622b328b2Sdan# PagerRollback(<in-memory-db>) 110722b328b2Sdan# PagerRollback(<file-db>) 110822b328b2Sdan# 110922b328b2Sdando_faultsim_test pagerfault-23 -prep { 111022b328b2Sdan sqlite3 db :memory: 1111fda06befSmistachkin foreach f [glob -nocomplain test.db*] { forcedelete $f } 111222b328b2Sdan db eval { 111322b328b2Sdan ATTACH 'test.db2' AS aux; 111422b328b2Sdan CREATE TABLE t1(a, b); 111522b328b2Sdan CREATE TABLE aux.t2(a, b); 111622b328b2Sdan } 111722b328b2Sdan} -body { 111822b328b2Sdan execsql { 111922b328b2Sdan BEGIN; 112022b328b2Sdan INSERT INTO t1 VALUES(1,2); 112122b328b2Sdan INSERT INTO t2 VALUES(3,4); 112222b328b2Sdan COMMIT; 112322b328b2Sdan } 112422b328b2Sdan} -test { 112522b328b2Sdan faultsim_test_result {0 {}} 112622b328b2Sdan faultsim_integrity_check 112722b328b2Sdan} 112822b328b2Sdan 112922b328b2Sdando_faultsim_test pagerfault-24 -prep { 113022b328b2Sdan faultsim_delete_and_reopen 113122b328b2Sdan db eval { PRAGMA temp_store = file } 113222b328b2Sdan execsql { CREATE TABLE x(a, b) } 113322b328b2Sdan} -body { 113422b328b2Sdan execsql { CREATE TEMP TABLE t1(a, b) } 113522b328b2Sdan} -test { 11365653e4daSdan faultsim_test_result {0 {}} \ 11375653e4daSdan {1 {unable to open a temporary database file for storing temporary tables}} 113822b328b2Sdan set ic [db eval { PRAGMA temp.integrity_check }] 113922b328b2Sdan if {$ic != "ok"} { error "Integrity check: $ic" } 114022b328b2Sdan} 114122b328b2Sdan 11425653e4daSdanproc lockrows {n} { 11435653e4daSdan if {$n==0} { return "" } 11445653e4daSdan db eval { SELECT * FROM t1 WHERE oid = $n } { 11455653e4daSdan return [lockrows [expr {$n-1}]] 11465653e4daSdan } 11475653e4daSdan} 11485653e4daSdan 11491879b088Sdan 11505653e4daSdando_test pagerfault-25-pre1 { 11515653e4daSdan faultsim_delete_and_reopen 11525653e4daSdan db func a_string a_string 11535653e4daSdan execsql { 11545653e4daSdan PRAGMA page_size = 1024; 11555653e4daSdan PRAGMA auto_vacuum = 0; 11565653e4daSdan CREATE TABLE t1(a); 11575653e4daSdan INSERT INTO t1 VALUES(a_string(500)); 11585653e4daSdan INSERT INTO t1 SELECT a_string(500) FROM t1; 11595653e4daSdan INSERT INTO t1 SELECT a_string(500) FROM t1; 11605653e4daSdan INSERT INTO t1 SELECT a_string(500) FROM t1; 11615653e4daSdan INSERT INTO t1 SELECT a_string(500) FROM t1; 11625653e4daSdan INSERT INTO t1 SELECT a_string(500) FROM t1; 11635653e4daSdan } 11645653e4daSdan faultsim_save_and_close 11655653e4daSdan} {} 11661879b088Sdando_faultsim_test pagerfault-25 -prep { 11675653e4daSdan faultsim_restore_and_reopen 11685653e4daSdan db func a_string a_string 11695653e4daSdan set ::channel [db incrblob -readonly t1 a 1] 11705653e4daSdan execsql { 11715653e4daSdan PRAGMA cache_size = 10; 11725653e4daSdan BEGIN; 11735653e4daSdan INSERT INTO t1 VALUES(a_string(3000)); 11745653e4daSdan INSERT INTO t1 VALUES(a_string(3000)); 11755653e4daSdan } 11765653e4daSdan} -body { 11775653e4daSdan lockrows 30 11785653e4daSdan} -test { 11795653e4daSdan catch { lockrows 30 } 11801879b088Sdan catch { db eval COMMIT } 11815653e4daSdan close $::channel 11825653e4daSdan faultsim_test_result {0 {}} 11835653e4daSdan} 118422b328b2Sdan 11851879b088Sdando_faultsim_test pagerfault-26 -prep { 11861879b088Sdan faultsim_delete_and_reopen 11871879b088Sdan execsql { 11881879b088Sdan PRAGMA page_size = 1024; 11891879b088Sdan PRAGMA journal_mode = truncate; 11901879b088Sdan PRAGMA auto_vacuum = full; 11911879b088Sdan PRAGMA locking_mode=exclusive; 11921879b088Sdan CREATE TABLE t1(a, b); 11931879b088Sdan INSERT INTO t1 VALUES(1, 2); 11941879b088Sdan PRAGMA page_size = 4096; 11951879b088Sdan } 11961879b088Sdan} -body { 11971879b088Sdan execsql { 11981879b088Sdan VACUUM; 11991879b088Sdan } 12001879b088Sdan} -test { 12011879b088Sdan faultsim_test_result {0 {}} 12021879b088Sdan 12031879b088Sdan set contents [db eval {SELECT * FROM t1}] 12041879b088Sdan if {$contents != "1 2"} { error "Bad database contents ($contents)" } 12051879b088Sdan 1206*b8fff29cSdan if {[atomic_batch_write test.db]==0} { 12071879b088Sdan set sz [file size test.db] 12081879b088Sdan if {$testrc!=0 && $sz!=1024*3 && $sz!=4096*3} { 1209*b8fff29cSdan error "Expected file size 3072 or 12288 bytes - actual size $sz bytes" 12101879b088Sdan } 12111879b088Sdan if {$testrc==0 && $sz!=4096*3} { 12121879b088Sdan error "Expected file size to be 12288 bytes - actual size $sz bytes" 12131879b088Sdan } 12141879b088Sdan } 1215*b8fff29cSdan} 12161879b088Sdan 1217f5d3df40Sdando_test pagerfault-27-pre { 1218f5d3df40Sdan faultsim_delete_and_reopen 1219f5d3df40Sdan db func a_string a_string 1220f5d3df40Sdan execsql { 1221f5d3df40Sdan PRAGMA page_size = 1024; 1222f5d3df40Sdan CREATE TABLE t1(a, b); 1223f5d3df40Sdan CREATE TABLE t2(a UNIQUE, b UNIQUE); 1224f5d3df40Sdan INSERT INTO t2 VALUES( a_string(800), a_string(800) ); 1225f5d3df40Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1226f5d3df40Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1227f5d3df40Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1228f5d3df40Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1229f5d3df40Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1230f5d3df40Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1231f5d3df40Sdan INSERT INTO t1 VALUES (a_string(20000), a_string(20000)); 1232f5d3df40Sdan } 1233f5d3df40Sdan faultsim_save_and_close 1234f5d3df40Sdan} {} 1235f5d3df40Sdando_faultsim_test pagerfault-27 -faults ioerr-persistent -prep { 1236f5d3df40Sdan faultsim_restore_and_reopen 1237f5d3df40Sdan db func a_string a_string 1238f5d3df40Sdan execsql { 1239f5d3df40Sdan PRAGMA cache_size = 10; 1240f5d3df40Sdan BEGIN EXCLUSIVE; 1241f5d3df40Sdan } 1242f5d3df40Sdan set ::channel [db incrblob t1 a 1] 1243f5d3df40Sdan} -body { 1244f5d3df40Sdan puts $::channel [string repeat abc 6000] 1245f5d3df40Sdan flush $::channel 1246f5d3df40Sdan} -test { 12475f848c3aSdan catchsql { UPDATE t2 SET a = a_string(800), b = a_string(800) } 1248f5d3df40Sdan catch { close $::channel } 12495f848c3aSdan catchsql { ROLLBACK } 1250f5d3df40Sdan faultsim_integrity_check 1251f5d3df40Sdan} 125259257dc6Sdan 1253d7a558a9Sdan 1254db082408Sdan#------------------------------------------------------------------------- 1255db082408Sdan# 1256db082408Sdando_test pagerfault-28-pre { 1257db082408Sdan faultsim_delete_and_reopen 1258db082408Sdan db func a_string a_string 1259db082408Sdan execsql { 1260db082408Sdan PRAGMA page_size = 512; 1261db082408Sdan 1262db082408Sdan PRAGMA journal_mode = wal; 1263db082408Sdan PRAGMA wal_autocheckpoint = 0; 1264db082408Sdan PRAGMA cache_size = 100000; 1265db082408Sdan 1266db082408Sdan BEGIN; 1267db082408Sdan CREATE TABLE t2(a UNIQUE, b UNIQUE); 1268db082408Sdan INSERT INTO t2 VALUES( a_string(800), a_string(800) ); 1269db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1270db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1271db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1272db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1273db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1274db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1275db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1276db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1277db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1278db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1279db082408Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1280db082408Sdan COMMIT; 1281db082408Sdan CREATE TABLE t1(a PRIMARY KEY, b); 1282db082408Sdan } 1283db082408Sdan expr {[file size test.db-shm] >= 96*1024} 1284db082408Sdan} {1} 1285db082408Sdanfaultsim_save_and_close 1286db082408Sdan 1287d7a558a9Sdando_faultsim_test pagerfault-28a -faults oom* -prep { 1288db082408Sdan faultsim_restore_and_reopen 12899b4c59faSdrh execsql { PRAGMA mmap_size=0 } 1290db082408Sdan 1291db082408Sdan sqlite3 db2 test.db 1292db082408Sdan db2 eval { SELECT count(*) FROM t2 } 1293db082408Sdan 1294db082408Sdan db func a_string a_string 1295db082408Sdan execsql { 1296db082408Sdan BEGIN; 1297db082408Sdan INSERT INTO t1 VALUES(a_string(2000), a_string(2000)); 1298db082408Sdan INSERT INTO t1 VALUES(a_string(2000), a_string(2000)); 1299db082408Sdan } 1300db082408Sdan set ::STMT [sqlite3_prepare db "SELECT * FROM t1 ORDER BY a" -1 DUMMY] 1301db082408Sdan sqlite3_step $::STMT 1302db082408Sdan} -body { 1303db082408Sdan execsql { ROLLBACK } 1304db082408Sdan} -test { 1305db082408Sdan db2 close 1306db082408Sdan sqlite3_finalize $::STMT 1307db082408Sdan catchsql { ROLLBACK } 1308db082408Sdan faultsim_integrity_check 1309db082408Sdan} 1310db082408Sdan 1311d7a558a9Sdanfaultsim_restore_and_reopen 1312d7a558a9Sdansqlite3 db2 test.db 1313d7a558a9Sdandb2 eval {SELECT count(*) FROM t2} 1314d7a558a9Sdandb close 1315d7a558a9Sdan 1316d7a558a9Sdando_faultsim_test pagerfault-28b -faults oom* -prep { 1317d7a558a9Sdan sqlite3 db test.db 1318d7a558a9Sdan} -body { 1319d7a558a9Sdan execsql { SELECT count(*) FROM t2 } 1320d7a558a9Sdan} -test { 1321d7a558a9Sdan faultsim_test_result {0 2048} 1322d7a558a9Sdan db close 1323d7a558a9Sdan} 1324d7a558a9Sdan 1325d7a558a9Sdandb2 close 1326d7a558a9Sdan 1327d7a558a9Sdan#------------------------------------------------------------------------- 1328d7a558a9Sdan# Try this: 1329d7a558a9Sdan# 1330d7a558a9Sdan# 1) Put the pager in ERROR state (error during rollback) 1331d7a558a9Sdan# 1332d7a558a9Sdan# 2) Next time the connection is used inject errors into all xWrite() and 1333d7a558a9Sdan# xUnlock() calls. This causes the hot-journal rollback to fail and 1334d7a558a9Sdan# the pager to declare its locking state UNKNOWN. 1335d7a558a9Sdan# 1336d7a558a9Sdan# 3) Same again. 1337d7a558a9Sdan# 1338d7a558a9Sdan# 4a) Stop injecting errors. Allow the rollback to succeed. Check that 1339d7a558a9Sdan# the database is Ok. Or, 1340d7a558a9Sdan# 1341d7a558a9Sdan# 4b) Close and reopen the db. Check that the db is Ok. 1342d7a558a9Sdan# 1343d7a558a9Sdanproc custom_injectinstall {} { 1344d7a558a9Sdan testvfs custom -default true 1345d7a558a9Sdan custom filter {xWrite xUnlock} 1346d7a558a9Sdan} 1347d7a558a9Sdanproc custom_injectuninstall {} { 1348d7a558a9Sdan catch {db close} 1349d7a558a9Sdan catch {db2 close} 1350d7a558a9Sdan custom delete 1351d7a558a9Sdan} 1352d7a558a9Sdanproc custom_injectstart {iFail} { 1353d7a558a9Sdan custom ioerr $iFail 1 1354d7a558a9Sdan} 1355d7a558a9Sdanproc custom_injectstop {} { 1356d7a558a9Sdan custom ioerr 1357d7a558a9Sdan} 1358d7a558a9Sdanset ::FAULTSIM(custom) [list \ 1359d7a558a9Sdan -injectinstall custom_injectinstall \ 1360d7a558a9Sdan -injectstart custom_injectstart \ 1361d7a558a9Sdan -injectstop custom_injectstop \ 1362d7a558a9Sdan -injecterrlist {{1 {disk I/O error}}} \ 1363d7a558a9Sdan -injectuninstall custom_injectuninstall \ 1364d7a558a9Sdan] 1365d7a558a9Sdan 1366d7a558a9Sdando_test pagerfault-29-pre { 1367d7a558a9Sdan faultsim_delete_and_reopen 1368d7a558a9Sdan db func a_string a_string 1369d7a558a9Sdan execsql { 1370d7a558a9Sdan PRAGMA page_size = 1024; 1371d7a558a9Sdan PRAGMA cache_size = 5; 1372d7a558a9Sdan 1373d7a558a9Sdan BEGIN; 1374d7a558a9Sdan CREATE TABLE t2(a UNIQUE, b UNIQUE); 1375d7a558a9Sdan INSERT INTO t2 VALUES( a_string(800), a_string(800) ); 1376d7a558a9Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1377d7a558a9Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1378d7a558a9Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1379d7a558a9Sdan INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2; 1380d7a558a9Sdan COMMIT; 1381d7a558a9Sdan } 1382d7a558a9Sdan expr {[file size test.db] >= 50*1024} 1383d7a558a9Sdan} {1} 1384d7a558a9Sdanfaultsim_save_and_close 1385d7a558a9Sdanforeach {tn tt} { 1386d7a558a9Sdan 29 { catchsql ROLLBACK } 1387d7a558a9Sdan 30 { db close ; sqlite3 db test.db } 1388d7a558a9Sdan} { 1389d7a558a9Sdan do_faultsim_test pagerfault-$tn -faults custom -prep { 1390d7a558a9Sdan faultsim_restore_and_reopen 1391d7a558a9Sdan db func a_string a_string 1392d7a558a9Sdan execsql { 1393d7a558a9Sdan PRAGMA cache_size = 5; 1394d7a558a9Sdan BEGIN; 1395d7a558a9Sdan UPDATE t2 SET a = a_string(799); 1396d7a558a9Sdan } 1397d7a558a9Sdan } -body { 1398d7a558a9Sdan catchsql ROLLBACK 1399d7a558a9Sdan catchsql ROLLBACK 1400d7a558a9Sdan catchsql ROLLBACK 1401d7a558a9Sdan } -test { 1402d7a558a9Sdan eval $::tt 1403d7a558a9Sdan if {"ok" != [db one {PRAGMA integrity_check}]} { 1404d7a558a9Sdan error "integrity check failed" 1405d7a558a9Sdan } 1406d7a558a9Sdan } 1407d7a558a9Sdan} 1408d7a558a9Sdan 1409d7a558a9Sdando_test pagerfault-31-pre { 1410d7a558a9Sdan sqlite3_shutdown 1411d7a558a9Sdan sqlite3_config_uri 1 1412d7a558a9Sdan} {SQLITE_OK} 1413d7a558a9Sdando_faultsim_test pagerfault-31 -faults oom* -body { 1414d7a558a9Sdan sqlite3 db {file:one?mode=memory&cache=shared} 1415d7a558a9Sdan db eval { 1416d7a558a9Sdan CREATE TABLE t1(x); 1417d7a558a9Sdan INSERT INTO t1 VALUES(1); 1418d7a558a9Sdan SELECT * FROM t1; 1419d7a558a9Sdan } 1420d7a558a9Sdan} -test { 1421d7a558a9Sdan faultsim_test_result {0 1} {1 {}} 1422d7a558a9Sdan catch { db close } 1423d7a558a9Sdan} 1424d7a558a9Sdansqlite3_shutdown 1425d7a558a9Sdansqlite3_config_uri 0 1426d7a558a9Sdan 1427d7a558a9Sdando_test pagerfault-32-pre { 1428d7a558a9Sdan reset_db 1429d7a558a9Sdan execsql { 1430d7a558a9Sdan CREATE TABLE t1(x); 1431d7a558a9Sdan INSERT INTO t1 VALUES('one'); 1432d7a558a9Sdan } 1433d7a558a9Sdan} {} 1434d7a558a9Sdanfaultsim_save_and_close 1435d7a558a9Sdan 1436d7a558a9Sdando_faultsim_test pagerfault-32 -prep { 1437d7a558a9Sdan faultsim_restore_and_reopen 1438d7a558a9Sdan db eval { SELECT * FROM t1; } 1439d7a558a9Sdan} -body { 1440d7a558a9Sdan execsql { SELECT * FROM t1; } 1441d7a558a9Sdan} -test { 1442d7a558a9Sdan faultsim_test_result {0 one} 1443d7a558a9Sdan} 1444d7a558a9Sdansqlite3_shutdown 1445d7a558a9Sdansqlite3_config_uri 0 1446d7a558a9Sdan 1447d7a558a9Sdando_faultsim_test pagerfault-33a -prep { 1448d7a558a9Sdan sqlite3 db :memory: 1449d7a558a9Sdan execsql { 1450d7a558a9Sdan CREATE TABLE t1(a, b); 1451d7a558a9Sdan INSERT INTO t1 VALUES(1, 2); 1452d7a558a9Sdan } 1453d7a558a9Sdan} -body { 1454d7a558a9Sdan execsql { VACUUM } 1455d7a558a9Sdan} -test { 1456d7a558a9Sdan faultsim_test_result {0 {}} 1457d7a558a9Sdan} 1458d7a558a9Sdando_faultsim_test pagerfault-33b -prep { 1459d7a558a9Sdan sqlite3 db "" 1460d7a558a9Sdan execsql { 1461d7a558a9Sdan CREATE TABLE t1(a, b); 1462d7a558a9Sdan INSERT INTO t1 VALUES(1, 2); 1463d7a558a9Sdan } 1464d7a558a9Sdan} -body { 1465d7a558a9Sdan execsql { VACUUM } 1466d7a558a9Sdan} -test { 1467d7a558a9Sdan faultsim_test_result {0 {}} 1468d7a558a9Sdan} 1469d7a558a9Sdan 1470d7a558a9Sdando_test pagerfault-34-pre { 1471d7a558a9Sdan reset_db 1472d7a558a9Sdan execsql { 1473d7a558a9Sdan CREATE TABLE t1(x PRIMARY KEY); 1474d7a558a9Sdan } 1475d7a558a9Sdan} {} 1476d7a558a9Sdanfaultsim_save_and_close 1477d7a558a9Sdando_faultsim_test pagerfault-34 -prep { 1478d7a558a9Sdan faultsim_restore_and_reopen 1479d7a558a9Sdan execsql { 1480d7a558a9Sdan BEGIN; 1481d7a558a9Sdan INSERT INTO t1 VALUES( randomblob(4000) ); 1482d7a558a9Sdan DELETE FROM t1; 1483d7a558a9Sdan } 1484d7a558a9Sdan} -body { 1485d7a558a9Sdan execsql COMMIT 1486d7a558a9Sdan} -test { 1487d7a558a9Sdan faultsim_test_result {0 {}} 1488d7a558a9Sdan} 1489d7a558a9Sdan 1490abd6d84aSdando_test pagerfault-35-pre { 1491abd6d84aSdan faultsim_delete_and_reopen 1492abd6d84aSdan execsql { 1493abd6d84aSdan CREATE TABLE t1(x PRIMARY KEY, y); 1494abd6d84aSdan INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); 1495abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 1496abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 1497abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 1498abd6d84aSdan } 1499abd6d84aSdan faultsim_save_and_close 1500abd6d84aSdan} {} 1501abd6d84aSdantestvfs tv -default 1 1502abd6d84aSdantv sectorsize 8192; 1503abd6d84aSdantv devchar [list] 1504abd6d84aSdando_faultsim_test pagerfault-35 -prep { 1505abd6d84aSdan faultsim_restore_and_reopen 1506abd6d84aSdan} -body { 1507abd6d84aSdan execsql { UPDATE t1 SET x=randomblob(200) } 1508abd6d84aSdan} -test { 1509abd6d84aSdan faultsim_test_result {0 {}} 1510abd6d84aSdan} 1511abd6d84aSdancatch {db close} 1512abd6d84aSdantv delete 1513abd6d84aSdan 1514abd6d84aSdansqlite3_shutdown 1515abd6d84aSdansqlite3_config_uri 1 1516abd6d84aSdando_test pagerfault-36-pre { 1517abd6d84aSdan faultsim_delete_and_reopen 1518abd6d84aSdan execsql { 1519abd6d84aSdan CREATE TABLE t1(x PRIMARY KEY, y); 1520abd6d84aSdan INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); 1521abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 1522abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 1523abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 1524abd6d84aSdan } 1525abd6d84aSdan faultsim_save_and_close 1526abd6d84aSdan} {} 1527abd6d84aSdando_faultsim_test pagerfault-36 -prep { 1528abd6d84aSdan faultsim_restore 1529abd6d84aSdan sqlite3 db file:test.db?cache=shared 1530abd6d84aSdan sqlite3 db2 file:test.db?cache=shared 1531abd6d84aSdan db2 eval { 1532abd6d84aSdan BEGIN; 1533abd6d84aSdan SELECT count(*) FROM sqlite_master; 1534abd6d84aSdan } 1535abd6d84aSdan db eval { 1536abd6d84aSdan PRAGMA cache_size = 1; 1537abd6d84aSdan BEGIN; 1538abd6d84aSdan UPDATE t1 SET x = randomblob(200); 1539abd6d84aSdan } 1540abd6d84aSdan} -body { 1541abd6d84aSdan execsql ROLLBACK db 1542abd6d84aSdan} -test { 1543abd6d84aSdan catch { db eval {UPDATE t1 SET x = randomblob(200)} } 1544abd6d84aSdan faultsim_test_result {0 {}} 1545abd6d84aSdan catch { db close } 1546abd6d84aSdan catch { db2 close } 1547abd6d84aSdan} 1548abd6d84aSdan 1549abd6d84aSdansqlite3_shutdown 1550abd6d84aSdansqlite3_config_uri 0 1551d0879badSdansqlite3_initialize 1552d7a558a9Sdan 1553b0ac3e3aSdanfinish_test 1554