blob: 0af8d518076c1cbd29a8e0be28d156f4a71ead1a [file] [log] [blame]
danb0ac3e32010-06-16 10:55:42 +00001# 2010 June 15
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
18set a_string_counter 1
19proc a_string {n} {
20 global a_string_counter
21 incr a_string_counter
22 string range [string repeat "${a_string_counter}." $n] 1 $n
23}
24db func a_string a_string
25
26#-------------------------------------------------------------------------
27# Test fault-injection while rolling back a hot-journal file.
28#
29do_test pagerfault-1-pre1 {
30 execsql {
31 PRAGMA journal_mode = DELETE;
32 PRAGMA cache_size = 10;
33 CREATE TABLE t1(a UNIQUE, b UNIQUE);
34 INSERT INTO t1 VALUES(a_string(200), a_string(300));
35 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
36 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
37 BEGIN;
38 INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
39 INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
40 INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
41 INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
42 }
43 faultsim_save_and_close
44} {}
45do_faultsim_test pagerfault-1 -prep {
46 faultsim_restore_and_reopen
47} -body {
48 execsql { SELECT count(*) FROM t1 }
49} -test {
50 faultsim_test_result {0 4}
51 faultsim_integrity_check
52 if {[db one { SELECT count(*) FROM t1 }] != 4} {
53 error "Database content appears incorrect"
54 }
55}
56
57#-------------------------------------------------------------------------
dande4996e2010-06-19 11:30:41 +000058# Test fault-injection while rolling back a hot-journal file with a
59# page-size different from the current value stored on page 1 of the
60# database file.
61#
62do_test pagerfault-2-pre1 {
63 testvfs tv -default 1
64 tv filter xSync
65 tv script xSyncCb
66 proc xSyncCb {filename args} {
67 if {[string match *journal filename]==0} faultsim_save
68 }
69 faultsim_delete_and_reopen
70 execsql {
71 PRAGMA page_size = 4096;
72 BEGIN;
73 CREATE TABLE abc(a, b, c);
74 INSERT INTO abc VALUES('o', 't', 't');
75 INSERT INTO abc VALUES('f', 'f', 's');
76 INSERT INTO abc SELECT * FROM abc; -- 4
77 INSERT INTO abc SELECT * FROM abc; -- 8
78 INSERT INTO abc SELECT * FROM abc; -- 16
79 INSERT INTO abc SELECT * FROM abc; -- 32
80 INSERT INTO abc SELECT * FROM abc; -- 64
81 INSERT INTO abc SELECT * FROM abc; -- 128
82 INSERT INTO abc SELECT * FROM abc; -- 256
83 COMMIT;
84 PRAGMA page_size = 1024;
85 VACUUM;
86 }
87 db close
88 tv delete
89} {}
90do_faultsim_test pagerfault-2 -prep {
91 faultsim_restore_and_reopen
92} -body {
93 execsql { SELECT * FROM abc }
94} -test {
95 set answer [split [string repeat "ottffs" 128] ""]
96 faultsim_test_result [list 0 $answer]
97 faultsim_integrity_check
98 set res [db eval { SELECT * FROM abc }]
99 if {$res != $answer} { error "Database content appears incorrect ($res)" }
100} -faults oom-transient
101
102#-------------------------------------------------------------------------
danb0ac3e32010-06-16 10:55:42 +0000103# Test fault-injection while rolling back hot-journals that were created
104# as part of a multi-file transaction.
105#
dande4996e2010-06-19 11:30:41 +0000106do_test pagerfault-3-pre1 {
danb0ac3e32010-06-16 10:55:42 +0000107 testvfs tstvfs -default 1
108 tstvfs filter xDelete
109 tstvfs script xDeleteCallback
110
111 proc xDeleteCallback {method file args} {
112 set file [file tail $file]
113 if { [string match *mj* $file] } { faultsim_save }
114 }
115
116 faultsim_delete_and_reopen
117 db func a_string a_string
118
119 execsql {
120 ATTACH 'test.db2' AS aux;
121 PRAGMA journal_mode = DELETE;
122 PRAGMA main.cache_size = 10;
123 PRAGMA aux.cache_size = 10;
124
125 CREATE TABLE t1(a UNIQUE, b UNIQUE);
126 CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
127 INSERT INTO t1 VALUES(a_string(200), a_string(300));
128 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
129 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
130 INSERT INTO t2 SELECT * FROM t1;
131
132 BEGIN;
133 INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
134 INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
135 INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
136 INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
137 REPLACE INTO t2 SELECT * FROM t1;
138 COMMIT;
139 }
140
141 db close
142 tstvfs delete
143} {}
dande4996e2010-06-19 11:30:41 +0000144do_faultsim_test pagerfault-3 -faults ioerr-persistent -prep {
danb0ac3e32010-06-16 10:55:42 +0000145 faultsim_restore_and_reopen
146} -body {
147 execsql {
148 ATTACH 'test.db2' AS aux;
149 SELECT count(*) FROM t2;
150 SELECT count(*) FROM t1;
151 }
152} -test {
153 faultsim_test_result {0 {4 4}} {1 {unable to open database: test.db2}}
154 faultsim_integrity_check
danb0ac3e32010-06-16 10:55:42 +0000155 catchsql { ATTACH 'test.db2' AS aux }
156 if {[db one { SELECT count(*) FROM t1 }] != 4
157 || [db one { SELECT count(*) FROM t2 }] != 4
158 } {
159 error "Database content appears incorrect"
160 }
161}
162
dande4996e2010-06-19 11:30:41 +0000163#-------------------------------------------------------------------------
164# Test fault-injection as part of a vanilla, no-transaction, INSERT
165# statement.
166#
167do_faultsim_test pagerfault-4 -prep {
168 faultsim_delete_and_reopen
169} -body {
170 execsql {
171 CREATE TABLE x(y);
172 INSERT INTO x VALUES('z');
173 SELECT * FROM x;
174 }
175} -test {
176 faultsim_test_result {0 z}
177 faultsim_integrity_check
178}
179
180#-------------------------------------------------------------------------
181# Test fault-injection as part of a commit when using journal_mode=PERSIST.
dan146ed782010-06-19 17:26:37 +0000182# Three different cases:
183#
184# pagerfault-5.1: With no journal_size_limit configured.
185# pagerfault-5.2: With a journal_size_limit configured.
186# pagerfault-5.4: Multi-file transaction. One connection has a
187# journal_size_limit of 0, the other has no limit.
dande4996e2010-06-19 11:30:41 +0000188#
189do_test pagerfault-5-pre1 {
190 faultsim_delete_and_reopen
191 db func a_string a_string
192 execsql {
193 CREATE TABLE t1(a UNIQUE, b UNIQUE);
194 INSERT INTO t1 VALUES(a_string(200), a_string(300));
195 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
196 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
197 }
198 faultsim_save_and_close
199} {}
200do_faultsim_test pagerfault-5.1 -prep {
201 faultsim_restore_and_reopen
202 db func a_string a_string
203 execsql { PRAGMA journal_mode = PERSIST }
204} -body {
205 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
206} -test {
207 faultsim_test_result {0 {}}
208 faultsim_integrity_check
209}
210do_faultsim_test pagerfault-5.2 -prep {
211 faultsim_restore_and_reopen
212 db func a_string a_string
213 execsql {
214 PRAGMA journal_mode = PERSIST;
215 PRAGMA journal_size_limit = 2048;
216 }
217} -body {
218 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
219} -test {
220 faultsim_test_result {0 {}}
221 faultsim_integrity_check
222}
dande4996e2010-06-19 11:30:41 +0000223do_faultsim_test pagerfault-5.3 -prep {
224 faultsim_restore_and_reopen
225 db func a_string a_string
226 file delete -force test2.db test2.db-journal test2.db-wal
227 execsql {
228 PRAGMA journal_mode = PERSIST;
229 ATTACH 'test2.db' AS aux;
230 PRAGMA aux.journal_mode = PERSIST;
231 PRAGMA aux.journal_size_limit = 0;
232 }
233} -body {
234 execsql {
235 BEGIN;
236 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
237 CREATE TABLE aux.t2 AS SELECT * FROM t1;
238 COMMIT;
239 }
240} -test {
241 faultsim_test_result {0 {}}
242}
243
dan153eda02010-06-21 07:45:47 +0000244#-------------------------------------------------------------------------
245# Test fault-injection as part of a commit when using
246# journal_mode=TRUNCATE.
247#
248do_test pagerfault-6-pre1 {
249 faultsim_delete_and_reopen
250 db func a_string a_string
251 execsql {
252 CREATE TABLE t1(a UNIQUE, b UNIQUE);
253 INSERT INTO t1 VALUES(a_string(200), a_string(300));
254 }
255 faultsim_save_and_close
256} {}
257do_faultsim_test pagerfault-6.1 -prep {
258 faultsim_restore_and_reopen
259 db func a_string a_string
260 execsql { PRAGMA journal_mode = TRUNCATE }
261} -body {
262 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
263} -test {
264 faultsim_test_result {0 {}}
265 faultsim_integrity_check
266}
267
dan146ed782010-06-19 17:26:37 +0000268# The following was an attempt to get a bitvec malloc to fail. Didn't work.
269#
270# do_test pagerfault-6-pre1 {
271# faultsim_delete_and_reopen
272# execsql {
273# CREATE TABLE t1(x, y, UNIQUE(x, y));
274# INSERT INTO t1 VALUES(1, randomblob(1501));
275# INSERT INTO t1 VALUES(2, randomblob(1502));
276# INSERT INTO t1 VALUES(3, randomblob(1503));
277# INSERT INTO t1 VALUES(4, randomblob(1504));
278# INSERT INTO t1
279# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
280# INSERT INTO t1
281# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
282# INSERT INTO t1
283# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
284# INSERT INTO t1
285# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
286# }
287# faultsim_save_and_close
288# } {}
289# do_faultsim_test pagerfault-6 -prep {
290# faultsim_restore_and_reopen
291# } -body {
292# execsql {
293# BEGIN;
294# UPDATE t1 SET x=x+4 WHERE x=1;
295# SAVEPOINT one;
296# UPDATE t1 SET x=x+4 WHERE x=2;
297# SAVEPOINT three;
298# UPDATE t1 SET x=x+4 WHERE x=3;
299# SAVEPOINT four;
300# UPDATE t1 SET x=x+4 WHERE x=4;
301# RELEASE three;
302# COMMIT;
303# SELECT DISTINCT x FROM t1;
304# }
305# } -test {
306# faultsim_test_result {0 {5 6 7 8}}
307# faultsim_integrity_check
308# }
309
danb0ac3e32010-06-16 10:55:42 +0000310finish_test