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:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>