blob: 07d525ca9e4c99b4e270f245bbb2c78de10171c8 [file] [log] [blame]
dan213ca0a2011-03-28 19:10:06 +00001# 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
13set testdir [file dirname $argv0]
14source $testdir/tester.tcl
15source $testdir/lock_common.tcl
16source $testdir/malloc_common.tcl
17
18if {[llength [info commands test_syscall]]==0} {
19 finish_test
20 return
21}
22
23set testprefix sysfault
24
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_close
45
dan213ca0a2011-03-28 19:10:06 +000046
dan5ef47bf2011-03-29 18:28:35 +000047set open_and_write_body {
dan213ca0a2011-03-28 19:10:06 +000048 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 }
dan5ef47bf2011-03-29 18:28:35 +000058}
59
60proc vfsfault_install {} { test_syscall install {open getcwd} }
61do_faultsim_test 1 -faults vfsfault-* -prep {
62 faultsim_restore
63} -body $open_and_write_body -test {
dan213ca0a2011-03-28 19:10:06 +000064 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
dan661d71a2011-03-30 19:08:03 +000069#-------------------------------------------------------------------------
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.
dan5ef47bf2011-03-29 18:28:35 +000074#
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_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
dan60939d02011-03-29 15:40:55 +000092#-------------------------------------------------------------------------
dan661d71a2011-03-30 19:08:03 +000093# Various errors in locking functions.
94#
95foreach vfs {unix unix-excl} {
96 foreach {tn errno errlist} {
danea83bc62011-04-01 11:56:32 +000097 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}}
dan661d71a2011-03-30 19:08:03 +0000104 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#-------------------------------------------------------------------------
dan60939d02011-03-29 15:40:55 +0000138# Check that a single EINTR error does not affect processing.
139#
140proc vfsfault_install {} {
141 test_syscall reset
dan661d71a2011-03-30 19:08:03 +0000142 test_syscall install {open ftruncate close read pread pread64 write fallocate}
dan60939d02011-03-29 15:40:55 +0000143}
144
145forcedelete test.db test.db2
146sqlite3 db test.db
147do_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
158do_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
dan661d71a2011-03-30 19:08:03 +0000165 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
dan60939d02011-03-29 15:40:55 +0000170
171 sqlite3 db test.db
dan661d71a2011-03-30 19:08:03 +0000172 file_control_chunksize_test db main 8192
173
dan60939d02011-03-29 15:40:55 +0000174 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');
dan661d71a2011-03-30 19:08:03 +0000180 INSERT INTO t1 VALUES(randomblob(10000), 0, 0);
dan60939d02011-03-29 15:40:55 +0000181 UPDATE t2 SET x = 2;
182 COMMIT;
dan661d71a2011-03-30 19:08:03 +0000183 DELETE FROM t1 WHERE length(a)>3;
dan60939d02011-03-29 15:40:55 +0000184 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
193do_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
dan5ef47bf2011-03-29 18:28:35 +0000219#-------------------------------------------------------------------------
dan5ef47bf2011-03-29 18:28:35 +0000220
dan661d71a2011-03-30 19:08:03 +0000221proc vfsfault_install {} {
222 test_syscall reset
223 test_syscall install {fstat fallocate}
224}
225do_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}
dan60939d02011-03-29 15:40:55 +0000245
dan213ca0a2011-03-28 19:10:06 +0000246finish_test
247