blob: 81a62ed7eac8b95ffc7c65ad1bebc7afef726582 [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
dan146ed782010-06-19 17:26:37 +0000244# The following was an attempt to get a bitvec malloc to fail. Didn't work.
245#
246# do_test pagerfault-6-pre1 {
247# faultsim_delete_and_reopen
248# execsql {
249# CREATE TABLE t1(x, y, UNIQUE(x, y));
250# INSERT INTO t1 VALUES(1, randomblob(1501));
251# INSERT INTO t1 VALUES(2, randomblob(1502));
252# INSERT INTO t1 VALUES(3, randomblob(1503));
253# INSERT INTO t1 VALUES(4, randomblob(1504));
254# INSERT INTO t1
255# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
256# INSERT INTO t1
257# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
258# INSERT INTO t1
259# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
260# INSERT INTO t1
261# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
262# }
263# faultsim_save_and_close
264# } {}
265# do_faultsim_test pagerfault-6 -prep {
266# faultsim_restore_and_reopen
267# } -body {
268# execsql {
269# BEGIN;
270# UPDATE t1 SET x=x+4 WHERE x=1;
271# SAVEPOINT one;
272# UPDATE t1 SET x=x+4 WHERE x=2;
273# SAVEPOINT three;
274# UPDATE t1 SET x=x+4 WHERE x=3;
275# SAVEPOINT four;
276# UPDATE t1 SET x=x+4 WHERE x=4;
277# RELEASE three;
278# COMMIT;
279# SELECT DISTINCT x FROM t1;
280# }
281# } -test {
282# faultsim_test_result {0 {5 6 7 8}}
283# faultsim_integrity_check
284# }
285
danb0ac3e32010-06-16 10:55:42 +0000286finish_test