AryaWu/sqlite
0
1# 2011 March 282#3# The author disclaims copyright to this source code. In place of4# a legal notice, here is a blessing:5#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.9#10#***********************************************************************11#12 13set testdir [file dirname $argv0]14source $testdir/tester.tcl15source $testdir/lock_common.tcl16source $testdir/malloc_common.tcl17 18if {[llength [info commands test_syscall]]==0} {19 finish_test20 return21} 22 23set testprefix sysfault24 25set FAULTSIM(vfsfault-transient) [list \26 -injectinstall vfsfault_install \27 -injectstart vfsfault_injectstart_t \28 -injectstop vfsfault_injectstop \29 -injecterrlist {} \30 -injectuninstall {test_syscall uninstall} \31]32set FAULTSIM(vfsfault-persistent) [list \33 -injectinstall vfsfault_install \34 -injectstart vfsfault_injectstart_p \35 -injectstop vfsfault_injectstop \36 -injecterrlist {} \37 -injectuninstall {test_syscall uninstall} \38]39 40proc vfsfault_injectstart_t {iFail} { test_syscall fault $iFail 0 }41proc vfsfault_injectstart_p {iFail} { test_syscall fault $iFail 1 }42proc vfsfault_injectstop {} { test_syscall fault }43 44faultsim_save_and_close45 46 47set open_and_write_body {48 sqlite3 db test.db49 db eval {50 CREATE TABLE t1(a, b);51 INSERT INTO t1 VALUES(1, 2);52 PRAGMA journal_mode = WAL;53 INSERT INTO t1 VALUES(3, 4);54 SELECT * FROM t1;55 CREATE TEMP TABLE t2(x);56 INSERT INTO t2 VALUES('y');57 }58}59 60proc vfsfault_install {} { test_syscall install {open getcwd} }61do_faultsim_test 1 -faults vfsfault-* -prep {62 faultsim_restore63} -body $open_and_write_body -test {64 faultsim_test_result {0 {wal 1 2 3 4}} \65 {1 {unable to open database file}} \66 {1 {attempt to write a readonly database}}67}68 69#-------------------------------------------------------------------------70# Errors in the fstat() function when opening and writing a file. Cases71# where fstat() fails and sets errno to ENOMEM and EOVERFLOW are both72# tested. EOVERFLOW is interpreted as meaning that a file on disk is73# too large to be opened by the OS.74#75foreach {tn errno errlist} {76 1 ENOMEM {{disk I/O error}}77 2 EOVERFLOW {{disk I/O error} {large file support is disabled}}78} {79 proc vfsfault_install {} { test_syscall install fstat }80 set errs [list]81 foreach e $errlist { lappend errs [list 1 $e] }82 do_faultsim_test 1.2.$tn -faults vfsfault-* -prep {83 faultsim_restore84 } -body "85 test_syscall errno fstat $errno86 $open_and_write_body 87 " -test "88 faultsim_test_result {0 {wal 1 2 3 4}} $errs89 "90}91 92#-------------------------------------------------------------------------93# Various errors in locking functions. 94#95foreach vfs {unix unix-excl} {96 foreach {tn errno errlist} {97 1 EAGAIN {{database is locked} {disk I/O error}}98 2 ETIMEDOUT {{database is locked} {disk I/O error}}99 3 EBUSY {{database is locked} {disk I/O error}}100 4 EINTR {{database is locked} {disk I/O error}}101 5 ENOLCK {{database is locked} {disk I/O error}}102 6 EACCES {{database is locked} {disk I/O error}}103 7 EPERM {{access permission denied} {disk I/O error}}104 8 EDEADLK {{disk I/O error}}105 9 ENOMEM {{disk I/O error}}106 } {107 proc vfsfault_install {} { test_syscall install fcntl }108 set errs [list]109 foreach e $errlist { lappend errs [list 1 $e] }110 111 set body [string map [list %VFS% $vfs] {112 sqlite3 db test.db113 db eval {114 CREATE TABLE t1(a, b);115 INSERT INTO t1 VALUES(1, 2);116 }117 set fd [open test.db-journal w]118 puts $fd "hello world"119 close $fd120 sqlite3 db test.db -vfs %VFS%121 db eval {122 SELECT * FROM t1;123 }124 }]125 126 do_faultsim_test 1.3.$vfs.$tn -faults vfsfault-* -prep {127 faultsim_restore128 } -body "129 test_syscall errno fcntl $errno130 $body131 " -test "132 faultsim_test_result {0 {1 2}} $errs133 "134 }135}136 137#-------------------------------------------------------------------------138# Check that a single EINTR error does not affect processing.139#140proc vfsfault_install {} { 141 test_syscall reset142 test_syscall install {open ftruncate close read pread pread64 write fallocate}143}144 145forcedelete test.db test.db2146sqlite3 db test.db147do_test 2.setup {148 execsql {149 CREATE TABLE t1(a, b, c, PRIMARY KEY(a));150 INSERT INTO t1 VALUES('abc', 'def', 'ghi');151 ATTACH 'test.db2' AS 'aux';152 CREATE TABLE aux.t2(x);153 INSERT INTO t2 VALUES(1);154 }155 faultsim_save_and_close156} {}157 158do_faultsim_test 2.1 -faults vfsfault-transient -prep {159 catch { db close }160 faultsim_restore161} -body {162 test_syscall errno open EINTR163 test_syscall errno ftruncate EINTR164 test_syscall errno close EINTR165 test_syscall errno read EINTR166 test_syscall errno pread EINTR167 test_syscall errno pread64 EINTR168 test_syscall errno write EINTR169 test_syscall errno fallocate EINTR170 171 sqlite3 db test.db172 file_control_chunksize_test db main 8192173 174 set res [db eval {175 ATTACH 'test.db2' AS 'aux';176 SELECT * FROM t1;177 PRAGMA journal_mode = truncate;178 BEGIN;179 INSERT INTO t1 VALUES('jkl', 'mno', 'pqr');180 INSERT INTO t1 VALUES(randomblob(10000), 0, 0);181 UPDATE t2 SET x = 2;182 COMMIT;183 DELETE FROM t1 WHERE length(a)>3;184 SELECT * FROM t1;185 SELECT * FROM t2;186 }]187 db close188 set res189} -test {190 faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}}191}192 193do_faultsim_test 2.2 -faults vfsfault-* -prep {194 catch { db close }195 faultsim_restore196} -body {197 sqlite3 db test.db198 set res [db eval {199 ATTACH 'test.db2' AS 'aux';200 SELECT * FROM t1;201 PRAGMA journal_mode = truncate;202 BEGIN;203 INSERT INTO t1 VALUES('jkl', 'mno', 'pqr');204 UPDATE t2 SET x = 2;205 COMMIT;206 SELECT * FROM t1;207 SELECT * FROM t2;208 }]209 db close210 set res211} -test {212 faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}} \213 {1 {unable to open database file}} \214 {1 {unable to open database: test.db2}} \215 {1 {attempt to write a readonly database}} \216 {1 {disk I/O error}} 217}218 219#-------------------------------------------------------------------------220 221proc vfsfault_install {} { 222 test_syscall reset223 test_syscall install {fstat fallocate}224}225do_faultsim_test 3 -faults vfsfault-* -prep {226 faultsim_delete_and_reopen227 file_control_chunksize_test db main 8192228 execsql {229 PRAGMA synchronous=OFF;230 CREATE TABLE t1(a, b);231 BEGIN;232 SELECT * FROM t1;233 }234} -body {235 test_syscall errno fstat EIO236 test_syscall errno fallocate EIO237 238 execsql {239 INSERT INTO t1 VALUES(randomblob(10000), randomblob(10000));240 SELECT length(a) + length(b) FROM t1;241 COMMIT;242 }243} -test {244 faultsim_test_result {0 20000}245}246 247#-------------------------------------------------------------------------248# Test errors in mmap().249#250proc vfsfault_install {} { 251 test_syscall reset252 test_syscall install {mmap}253}254 255faultsim_delete_and_reopen256execsql {257 CREATE TABLE t1(a, b);258 INSERT INTO t1 VALUES(1, 2);259}260faultsim_save_and_close261 262do_faultsim_test 4 -faults vfsfault-* -prep {263 faultsim_restore_and_reopen264 file_control_chunksize_test db main 8192265 execsql { 266 PRAGMA mmap_size = 1000000;267 }268} -body {269 test_syscall errno mmap EACCES270 271 execsql {272 SELECT * FROM t1;273 }274} -test {275 faultsim_test_result {0 {1 2}} {1 {disk I/O error}}276}277 278finish_test279 