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 #------------------------------------------------------------------------- | |
247 # Test errors in mmap(). | |
248 # | |
249 proc vfsfault_install {} { | |
250 test_syscall reset | |
251 test_syscall install {mmap} | |
252 } | |
253 | |
254 faultsim_delete_and_reopen | |
255 execsql { | |
256 CREATE TABLE t1(a, b); | |
257 INSERT INTO t1 VALUES(1, 2); | |
258 } | |
259 faultsim_save_and_close | |
260 | |
261 do_faultsim_test 4 -faults vfsfault-* -prep { | |
262 faultsim_restore_and_reopen | |
263 file_control_chunksize_test db main 8192 | |
264 execsql { | |
265 PRAGMA mmap_size = 1000000; | |
266 } | |
267 } -body { | |
268 test_syscall errno mmap EACCES | |
269 | |
270 execsql { | |
271 SELECT * FROM t1; | |
272 } | |
273 } -test { | |
274 faultsim_test_result {0 {1 2}} {1 {disk I/O error}} | |
275 } | |
276 | |
277 finish_test | |
OLD | NEW |