1213ca0a8Sdan# 2011 March 28 2213ca0a8Sdan# 3213ca0a8Sdan# The author disclaims copyright to this source code. In place of 4213ca0a8Sdan# a legal notice, here is a blessing: 5213ca0a8Sdan# 6213ca0a8Sdan# May you do good and not evil. 7213ca0a8Sdan# May you find forgiveness for yourself and forgive others. 8213ca0a8Sdan# May you share freely, never taking more than you give. 9213ca0a8Sdan# 10213ca0a8Sdan#*********************************************************************** 11213ca0a8Sdan# 12213ca0a8Sdan 13213ca0a8Sdanset testdir [file dirname $argv0] 14213ca0a8Sdansource $testdir/tester.tcl 15213ca0a8Sdansource $testdir/lock_common.tcl 16213ca0a8Sdansource $testdir/malloc_common.tcl 17213ca0a8Sdan 18213ca0a8Sdanif {[llength [info commands test_syscall]]==0} { 19213ca0a8Sdan finish_test 20213ca0a8Sdan return 21213ca0a8Sdan} 22213ca0a8Sdan 23213ca0a8Sdanset testprefix sysfault 24213ca0a8Sdan 25213ca0a8Sdanset FAULTSIM(vfsfault-transient) [list \ 26213ca0a8Sdan -injectinstall vfsfault_install \ 27213ca0a8Sdan -injectstart vfsfault_injectstart_t \ 28213ca0a8Sdan -injectstop vfsfault_injectstop \ 29213ca0a8Sdan -injecterrlist {} \ 30213ca0a8Sdan -injectuninstall {test_syscall uninstall} \ 31213ca0a8Sdan] 32213ca0a8Sdanset FAULTSIM(vfsfault-persistent) [list \ 33213ca0a8Sdan -injectinstall vfsfault_install \ 34213ca0a8Sdan -injectstart vfsfault_injectstart_p \ 35213ca0a8Sdan -injectstop vfsfault_injectstop \ 36213ca0a8Sdan -injecterrlist {} \ 37213ca0a8Sdan -injectuninstall {test_syscall uninstall} \ 38213ca0a8Sdan] 39213ca0a8Sdan 40213ca0a8Sdanproc vfsfault_injectstart_t {iFail} { test_syscall fault $iFail 0 } 41213ca0a8Sdanproc vfsfault_injectstart_p {iFail} { test_syscall fault $iFail 1 } 42213ca0a8Sdanproc vfsfault_injectstop {} { test_syscall fault } 43213ca0a8Sdan 44213ca0a8Sdanfaultsim_save_and_close 45213ca0a8Sdan 46213ca0a8Sdan 475ef47bf0Sdanset open_and_write_body { 48213ca0a8Sdan sqlite3 db test.db 49213ca0a8Sdan db eval { 50213ca0a8Sdan CREATE TABLE t1(a, b); 51213ca0a8Sdan INSERT INTO t1 VALUES(1, 2); 52213ca0a8Sdan PRAGMA journal_mode = WAL; 53213ca0a8Sdan INSERT INTO t1 VALUES(3, 4); 54213ca0a8Sdan SELECT * FROM t1; 55213ca0a8Sdan CREATE TEMP TABLE t2(x); 56213ca0a8Sdan INSERT INTO t2 VALUES('y'); 57213ca0a8Sdan } 585ef47bf0Sdan} 595ef47bf0Sdan 605ef47bf0Sdanproc vfsfault_install {} { test_syscall install {open getcwd} } 615ef47bf0Sdando_faultsim_test 1 -faults vfsfault-* -prep { 625ef47bf0Sdan faultsim_restore 635ef47bf0Sdan} -body $open_and_write_body -test { 64213ca0a8Sdan faultsim_test_result {0 {wal 1 2 3 4}} \ 65213ca0a8Sdan {1 {unable to open database file}} \ 66213ca0a8Sdan {1 {attempt to write a readonly database}} 67213ca0a8Sdan} 68213ca0a8Sdan 69661d71afSdan#------------------------------------------------------------------------- 70661d71afSdan# Errors in the fstat() function when opening and writing a file. Cases 71661d71afSdan# where fstat() fails and sets errno to ENOMEM and EOVERFLOW are both 72661d71afSdan# tested. EOVERFLOW is interpreted as meaning that a file on disk is 73661d71afSdan# too large to be opened by the OS. 745ef47bf0Sdan# 755ef47bf0Sdanforeach {tn errno errlist} { 765ef47bf0Sdan 1 ENOMEM {{disk I/O error}} 775ef47bf0Sdan 2 EOVERFLOW {{disk I/O error} {large file support is disabled}} 785ef47bf0Sdan} { 795ef47bf0Sdan proc vfsfault_install {} { test_syscall install fstat } 805ef47bf0Sdan set errs [list] 815ef47bf0Sdan foreach e $errlist { lappend errs [list 1 $e] } 825ef47bf0Sdan do_faultsim_test 1.2.$tn -faults vfsfault-* -prep { 835ef47bf0Sdan faultsim_restore 845ef47bf0Sdan } -body " 855ef47bf0Sdan test_syscall errno fstat $errno 865ef47bf0Sdan $open_and_write_body 875ef47bf0Sdan " -test " 885ef47bf0Sdan faultsim_test_result {0 {wal 1 2 3 4}} $errs 895ef47bf0Sdan " 905ef47bf0Sdan} 915ef47bf0Sdan 9260939d0aSdan#------------------------------------------------------------------------- 93661d71afSdan# Various errors in locking functions. 94661d71afSdan# 95661d71afSdanforeach vfs {unix unix-excl} { 96661d71afSdan foreach {tn errno errlist} { 97ea83bc61Sdan 1 EAGAIN {{database is locked} {disk I/O error}} 98ea83bc61Sdan 2 ETIMEDOUT {{database is locked} {disk I/O error}} 99ea83bc61Sdan 3 EBUSY {{database is locked} {disk I/O error}} 100ea83bc61Sdan 4 EINTR {{database is locked} {disk I/O error}} 101ea83bc61Sdan 5 ENOLCK {{database is locked} {disk I/O error}} 102ea83bc61Sdan 6 EACCES {{database is locked} {disk I/O error}} 103ea83bc61Sdan 7 EPERM {{access permission denied} {disk I/O error}} 104661d71afSdan 8 EDEADLK {{disk I/O error}} 105661d71afSdan 9 ENOMEM {{disk I/O error}} 106661d71afSdan } { 107661d71afSdan proc vfsfault_install {} { test_syscall install fcntl } 108661d71afSdan set errs [list] 109661d71afSdan foreach e $errlist { lappend errs [list 1 $e] } 110661d71afSdan 111661d71afSdan set body [string map [list %VFS% $vfs] { 112661d71afSdan sqlite3 db test.db 113661d71afSdan db eval { 114661d71afSdan CREATE TABLE t1(a, b); 115661d71afSdan INSERT INTO t1 VALUES(1, 2); 116661d71afSdan } 117661d71afSdan set fd [open test.db-journal w] 118661d71afSdan puts $fd "hello world" 119661d71afSdan close $fd 120661d71afSdan sqlite3 db test.db -vfs %VFS% 121661d71afSdan db eval { 122661d71afSdan SELECT * FROM t1; 123661d71afSdan } 124661d71afSdan }] 125661d71afSdan 126661d71afSdan do_faultsim_test 1.3.$vfs.$tn -faults vfsfault-* -prep { 127661d71afSdan faultsim_restore 128661d71afSdan } -body " 129661d71afSdan test_syscall errno fcntl $errno 130661d71afSdan $body 131661d71afSdan " -test " 132661d71afSdan faultsim_test_result {0 {1 2}} $errs 133661d71afSdan " 134661d71afSdan } 135661d71afSdan} 136661d71afSdan 137661d71afSdan#------------------------------------------------------------------------- 13860939d0aSdan# Check that a single EINTR error does not affect processing. 13960939d0aSdan# 14060939d0aSdanproc vfsfault_install {} { 14160939d0aSdan test_syscall reset 142661d71afSdan test_syscall install {open ftruncate close read pread pread64 write fallocate} 14360939d0aSdan} 14460939d0aSdan 14560939d0aSdanforcedelete test.db test.db2 14660939d0aSdansqlite3 db test.db 14760939d0aSdando_test 2.setup { 14860939d0aSdan execsql { 14960939d0aSdan CREATE TABLE t1(a, b, c, PRIMARY KEY(a)); 15060939d0aSdan INSERT INTO t1 VALUES('abc', 'def', 'ghi'); 15160939d0aSdan ATTACH 'test.db2' AS 'aux'; 15260939d0aSdan CREATE TABLE aux.t2(x); 15360939d0aSdan INSERT INTO t2 VALUES(1); 15460939d0aSdan } 15560939d0aSdan faultsim_save_and_close 15660939d0aSdan} {} 15760939d0aSdan 15860939d0aSdando_faultsim_test 2.1 -faults vfsfault-transient -prep { 15960939d0aSdan catch { db close } 16060939d0aSdan faultsim_restore 16160939d0aSdan} -body { 16260939d0aSdan test_syscall errno open EINTR 16360939d0aSdan test_syscall errno ftruncate EINTR 16460939d0aSdan test_syscall errno close EINTR 165661d71afSdan test_syscall errno read EINTR 166661d71afSdan test_syscall errno pread EINTR 167661d71afSdan test_syscall errno pread64 EINTR 168661d71afSdan test_syscall errno write EINTR 169661d71afSdan test_syscall errno fallocate EINTR 17060939d0aSdan 17160939d0aSdan sqlite3 db test.db 172661d71afSdan file_control_chunksize_test db main 8192 173661d71afSdan 17460939d0aSdan set res [db eval { 17560939d0aSdan ATTACH 'test.db2' AS 'aux'; 17660939d0aSdan SELECT * FROM t1; 17760939d0aSdan PRAGMA journal_mode = truncate; 17860939d0aSdan BEGIN; 17960939d0aSdan INSERT INTO t1 VALUES('jkl', 'mno', 'pqr'); 180661d71afSdan INSERT INTO t1 VALUES(randomblob(10000), 0, 0); 18160939d0aSdan UPDATE t2 SET x = 2; 18260939d0aSdan COMMIT; 183661d71afSdan DELETE FROM t1 WHERE length(a)>3; 18460939d0aSdan SELECT * FROM t1; 18560939d0aSdan SELECT * FROM t2; 18660939d0aSdan }] 18760939d0aSdan db close 18860939d0aSdan set res 18960939d0aSdan} -test { 19060939d0aSdan faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}} 19160939d0aSdan} 19260939d0aSdan 19360939d0aSdando_faultsim_test 2.2 -faults vfsfault-* -prep { 19460939d0aSdan catch { db close } 19560939d0aSdan faultsim_restore 19660939d0aSdan} -body { 19760939d0aSdan sqlite3 db test.db 19860939d0aSdan set res [db eval { 19960939d0aSdan ATTACH 'test.db2' AS 'aux'; 20060939d0aSdan SELECT * FROM t1; 20160939d0aSdan PRAGMA journal_mode = truncate; 20260939d0aSdan BEGIN; 20360939d0aSdan INSERT INTO t1 VALUES('jkl', 'mno', 'pqr'); 20460939d0aSdan UPDATE t2 SET x = 2; 20560939d0aSdan COMMIT; 20660939d0aSdan SELECT * FROM t1; 20760939d0aSdan SELECT * FROM t2; 20860939d0aSdan }] 20960939d0aSdan db close 21060939d0aSdan set res 21160939d0aSdan} -test { 21260939d0aSdan faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}} \ 21360939d0aSdan {1 {unable to open database file}} \ 21460939d0aSdan {1 {unable to open database: test.db2}} \ 21560939d0aSdan {1 {attempt to write a readonly database}} \ 21660939d0aSdan {1 {disk I/O error}} 21760939d0aSdan} 21860939d0aSdan 2195ef47bf0Sdan#------------------------------------------------------------------------- 2205ef47bf0Sdan 221661d71afSdanproc vfsfault_install {} { 222661d71afSdan test_syscall reset 223661d71afSdan test_syscall install {fstat fallocate} 224661d71afSdan} 225661d71afSdando_faultsim_test 3 -faults vfsfault-* -prep { 226661d71afSdan faultsim_delete_and_reopen 227661d71afSdan file_control_chunksize_test db main 8192 228661d71afSdan execsql { 229*c18ed977Sdrh PRAGMA synchronous=OFF; 230661d71afSdan CREATE TABLE t1(a, b); 231661d71afSdan BEGIN; 232661d71afSdan SELECT * FROM t1; 233661d71afSdan } 234661d71afSdan} -body { 235661d71afSdan test_syscall errno fstat EIO 236661d71afSdan test_syscall errno fallocate EIO 237661d71afSdan 238661d71afSdan execsql { 239661d71afSdan INSERT INTO t1 VALUES(randomblob(10000), randomblob(10000)); 240661d71afSdan SELECT length(a) + length(b) FROM t1; 241661d71afSdan COMMIT; 242661d71afSdan } 243661d71afSdan} -test { 244661d71afSdan faultsim_test_result {0 20000} 245661d71afSdan} 24660939d0aSdan 247893c0ffcSdan#------------------------------------------------------------------------- 248893c0ffcSdan# Test errors in mmap(). 249893c0ffcSdan# 250893c0ffcSdanproc vfsfault_install {} { 251893c0ffcSdan test_syscall reset 252893c0ffcSdan test_syscall install {mmap} 253893c0ffcSdan} 254893c0ffcSdan 255893c0ffcSdanfaultsim_delete_and_reopen 256893c0ffcSdanexecsql { 257893c0ffcSdan CREATE TABLE t1(a, b); 258893c0ffcSdan INSERT INTO t1 VALUES(1, 2); 259893c0ffcSdan} 260893c0ffcSdanfaultsim_save_and_close 261893c0ffcSdan 262893c0ffcSdando_faultsim_test 4 -faults vfsfault-* -prep { 263893c0ffcSdan faultsim_restore_and_reopen 264893c0ffcSdan file_control_chunksize_test db main 8192 265893c0ffcSdan execsql { 2669b4c59faSdrh PRAGMA mmap_size = 1000000; 267893c0ffcSdan } 268893c0ffcSdan} -body { 269893c0ffcSdan test_syscall errno mmap EACCES 270893c0ffcSdan 271893c0ffcSdan execsql { 272893c0ffcSdan SELECT * FROM t1; 273893c0ffcSdan } 274893c0ffcSdan} -test { 275893c0ffcSdan faultsim_test_result {0 {1 2}} {1 {disk I/O error}} 276893c0ffcSdan} 277893c0ffcSdan 278213ca0a8Sdanfinish_test 279