OLD | NEW |
(Empty) | |
| 1 # 2011 March 28 |
| 2 # |
| 3 # The author disclaims copyright to this source code. In place of |
| 4 # 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 |
| 13 set testdir [file dirname $argv0] |
| 14 source $testdir/tester.tcl |
| 15 source $testdir/lock_common.tcl |
| 16 source $testdir/malloc_common.tcl |
| 17 |
| 18 if {[llength [info commands test_syscall]]==0} { |
| 19 finish_test |
| 20 return |
| 21 } |
| 22 |
| 23 set testprefix sysfault |
| 24 |
| 25 set 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 ] |
| 32 set 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 |
| 40 proc vfsfault_injectstart_t {iFail} { test_syscall fault $iFail 0 } |
| 41 proc vfsfault_injectstart_p {iFail} { test_syscall fault $iFail 1 } |
| 42 proc vfsfault_injectstop {} { test_syscall fault } |
| 43 |
| 44 faultsim_save_and_close |
| 45 |
| 46 |
| 47 set open_and_write_body { |
| 48 sqlite3 db test.db |
| 49 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 |
| 60 proc vfsfault_install {} { test_syscall install {open getcwd} } |
| 61 do_faultsim_test 1 -faults vfsfault-* -prep { |
| 62 faultsim_restore |
| 63 } -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. Cases |
| 71 # where fstat() fails and sets errno to ENOMEM and EOVERFLOW are both |
| 72 # tested. EOVERFLOW is interpreted as meaning that a file on disk is |
| 73 # too large to be opened by the OS. |
| 74 # |
| 75 foreach {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_restore |
| 84 } -body " |
| 85 test_syscall errno fstat $errno |
| 86 $open_and_write_body |
| 87 " -test " |
| 88 faultsim_test_result {0 {wal 1 2 3 4}} $errs |
| 89 " |
| 90 } |
| 91 |
| 92 #------------------------------------------------------------------------- |
| 93 # Various errors in locking functions. |
| 94 # |
| 95 foreach 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.db |
| 113 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 $fd |
| 120 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_restore |
| 128 } -body " |
| 129 test_syscall errno fcntl $errno |
| 130 $body |
| 131 " -test " |
| 132 faultsim_test_result {0 {1 2}} $errs |
| 133 " |
| 134 } |
| 135 } |
| 136 |
| 137 #------------------------------------------------------------------------- |
| 138 # Check that a single EINTR error does not affect processing. |
| 139 # |
| 140 proc vfsfault_install {} { |
| 141 test_syscall reset |
| 142 test_syscall install {open ftruncate close read pread pread64 write fallocate} |
| 143 } |
| 144 |
| 145 forcedelete test.db test.db2 |
| 146 sqlite3 db test.db |
| 147 do_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_close |
| 156 } {} |
| 157 |
| 158 do_faultsim_test 2.1 -faults vfsfault-transient -prep { |
| 159 catch { db close } |
| 160 faultsim_restore |
| 161 } -body { |
| 162 test_syscall errno open EINTR |
| 163 test_syscall errno ftruncate EINTR |
| 164 test_syscall errno close EINTR |
| 165 test_syscall errno read EINTR |
| 166 test_syscall errno pread EINTR |
| 167 test_syscall errno pread64 EINTR |
| 168 test_syscall errno write EINTR |
| 169 test_syscall errno fallocate EINTR |
| 170 |
| 171 sqlite3 db test.db |
| 172 file_control_chunksize_test db main 8192 |
| 173 |
| 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 close |
| 188 set res |
| 189 } -test { |
| 190 faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}} |
| 191 } |
| 192 |
| 193 do_faultsim_test 2.2 -faults vfsfault-* -prep { |
| 194 catch { db close } |
| 195 faultsim_restore |
| 196 } -body { |
| 197 sqlite3 db test.db |
| 198 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 close |
| 210 set res |
| 211 } -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 |
| 221 proc vfsfault_install {} { |
| 222 test_syscall reset |
| 223 test_syscall install {fstat fallocate} |
| 224 } |
| 225 do_faultsim_test 3 -faults vfsfault-* -prep { |
| 226 faultsim_delete_and_reopen |
| 227 file_control_chunksize_test db main 8192 |
| 228 execsql { |
| 229 CREATE TABLE t1(a, b); |
| 230 BEGIN; |
| 231 SELECT * FROM t1; |
| 232 } |
| 233 } -body { |
| 234 test_syscall errno fstat EIO |
| 235 test_syscall errno fallocate EIO |
| 236 |
| 237 execsql { |
| 238 INSERT INTO t1 VALUES(randomblob(10000), randomblob(10000)); |
| 239 SELECT length(a) + length(b) FROM t1; |
| 240 COMMIT; |
| 241 } |
| 242 } -test { |
| 243 faultsim_test_result {0 20000} |
| 244 } |
| 245 |
| 246 finish_test |
| 247 |
OLD | NEW |