blob: ae1867c4bbc682bc073deabde42625a1d13f7a35 [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
dan273f3f02010-06-26 15:42:33 +000026if 1 {
27
danb0ac3e32010-06-16 10:55:42 +000028#-------------------------------------------------------------------------
29# Test fault-injection while rolling back a hot-journal file.
30#
31do_test pagerfault-1-pre1 {
32 execsql {
33 PRAGMA journal_mode = DELETE;
34 PRAGMA cache_size = 10;
35 CREATE TABLE t1(a UNIQUE, b UNIQUE);
36 INSERT INTO t1 VALUES(a_string(200), a_string(300));
37 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
38 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
39 BEGIN;
40 INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
41 INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
42 INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
43 INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
44 }
45 faultsim_save_and_close
46} {}
47do_faultsim_test pagerfault-1 -prep {
48 faultsim_restore_and_reopen
49} -body {
50 execsql { SELECT count(*) FROM t1 }
51} -test {
52 faultsim_test_result {0 4}
53 faultsim_integrity_check
54 if {[db one { SELECT count(*) FROM t1 }] != 4} {
55 error "Database content appears incorrect"
56 }
57}
58
59#-------------------------------------------------------------------------
dande4996e2010-06-19 11:30:41 +000060# Test fault-injection while rolling back a hot-journal file with a
61# page-size different from the current value stored on page 1 of the
62# database file.
63#
64do_test pagerfault-2-pre1 {
65 testvfs tv -default 1
66 tv filter xSync
67 tv script xSyncCb
68 proc xSyncCb {filename args} {
69 if {[string match *journal filename]==0} faultsim_save
70 }
71 faultsim_delete_and_reopen
72 execsql {
73 PRAGMA page_size = 4096;
74 BEGIN;
75 CREATE TABLE abc(a, b, c);
76 INSERT INTO abc VALUES('o', 't', 't');
77 INSERT INTO abc VALUES('f', 'f', 's');
78 INSERT INTO abc SELECT * FROM abc; -- 4
79 INSERT INTO abc SELECT * FROM abc; -- 8
80 INSERT INTO abc SELECT * FROM abc; -- 16
81 INSERT INTO abc SELECT * FROM abc; -- 32
82 INSERT INTO abc SELECT * FROM abc; -- 64
83 INSERT INTO abc SELECT * FROM abc; -- 128
84 INSERT INTO abc SELECT * FROM abc; -- 256
85 COMMIT;
86 PRAGMA page_size = 1024;
87 VACUUM;
88 }
89 db close
90 tv delete
91} {}
92do_faultsim_test pagerfault-2 -prep {
93 faultsim_restore_and_reopen
94} -body {
95 execsql { SELECT * FROM abc }
96} -test {
97 set answer [split [string repeat "ottffs" 128] ""]
98 faultsim_test_result [list 0 $answer]
99 faultsim_integrity_check
100 set res [db eval { SELECT * FROM abc }]
101 if {$res != $answer} { error "Database content appears incorrect ($res)" }
danec6ffc12010-06-24 19:16:06 +0000102}
dande4996e2010-06-19 11:30:41 +0000103
104#-------------------------------------------------------------------------
danb0ac3e32010-06-16 10:55:42 +0000105# Test fault-injection while rolling back hot-journals that were created
106# as part of a multi-file transaction.
107#
dande4996e2010-06-19 11:30:41 +0000108do_test pagerfault-3-pre1 {
danb0ac3e32010-06-16 10:55:42 +0000109 testvfs tstvfs -default 1
110 tstvfs filter xDelete
111 tstvfs script xDeleteCallback
112
113 proc xDeleteCallback {method file args} {
114 set file [file tail $file]
115 if { [string match *mj* $file] } { faultsim_save }
116 }
117
118 faultsim_delete_and_reopen
119 db func a_string a_string
120
121 execsql {
122 ATTACH 'test.db2' AS aux;
123 PRAGMA journal_mode = DELETE;
124 PRAGMA main.cache_size = 10;
125 PRAGMA aux.cache_size = 10;
126
127 CREATE TABLE t1(a UNIQUE, b UNIQUE);
128 CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
129 INSERT INTO t1 VALUES(a_string(200), a_string(300));
130 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
131 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
132 INSERT INTO t2 SELECT * FROM t1;
133
134 BEGIN;
135 INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
136 INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
137 INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
138 INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
139 REPLACE INTO t2 SELECT * FROM t1;
140 COMMIT;
141 }
142
143 db close
144 tstvfs delete
145} {}
danec6ffc12010-06-24 19:16:06 +0000146do_faultsim_test pagerfault-3 -prep {
danb0ac3e32010-06-16 10:55:42 +0000147 faultsim_restore_and_reopen
148} -body {
149 execsql {
150 ATTACH 'test.db2' AS aux;
151 SELECT count(*) FROM t2;
152 SELECT count(*) FROM t1;
153 }
154} -test {
155 faultsim_test_result {0 {4 4}} {1 {unable to open database: test.db2}}
156 faultsim_integrity_check
danb0ac3e32010-06-16 10:55:42 +0000157 catchsql { ATTACH 'test.db2' AS aux }
158 if {[db one { SELECT count(*) FROM t1 }] != 4
159 || [db one { SELECT count(*) FROM t2 }] != 4
160 } {
161 error "Database content appears incorrect"
162 }
163}
164
dande4996e2010-06-19 11:30:41 +0000165#-------------------------------------------------------------------------
166# Test fault-injection as part of a vanilla, no-transaction, INSERT
167# statement.
168#
169do_faultsim_test pagerfault-4 -prep {
170 faultsim_delete_and_reopen
171} -body {
172 execsql {
173 CREATE TABLE x(y);
174 INSERT INTO x VALUES('z');
175 SELECT * FROM x;
176 }
177} -test {
178 faultsim_test_result {0 z}
179 faultsim_integrity_check
180}
181
182#-------------------------------------------------------------------------
183# Test fault-injection as part of a commit when using journal_mode=PERSIST.
dan146ed782010-06-19 17:26:37 +0000184# Three different cases:
185#
186# pagerfault-5.1: With no journal_size_limit configured.
187# pagerfault-5.2: With a journal_size_limit configured.
188# pagerfault-5.4: Multi-file transaction. One connection has a
189# journal_size_limit of 0, the other has no limit.
dande4996e2010-06-19 11:30:41 +0000190#
191do_test pagerfault-5-pre1 {
192 faultsim_delete_and_reopen
193 db func a_string a_string
194 execsql {
195 CREATE TABLE t1(a UNIQUE, b UNIQUE);
196 INSERT INTO t1 VALUES(a_string(200), a_string(300));
197 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
198 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
199 }
200 faultsim_save_and_close
201} {}
202do_faultsim_test pagerfault-5.1 -prep {
203 faultsim_restore_and_reopen
204 db func a_string a_string
205 execsql { PRAGMA journal_mode = PERSIST }
206} -body {
207 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
208} -test {
209 faultsim_test_result {0 {}}
210 faultsim_integrity_check
211}
212do_faultsim_test pagerfault-5.2 -prep {
213 faultsim_restore_and_reopen
214 db func a_string a_string
215 execsql {
216 PRAGMA journal_mode = PERSIST;
217 PRAGMA journal_size_limit = 2048;
218 }
219} -body {
220 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
221} -test {
222 faultsim_test_result {0 {}}
223 faultsim_integrity_check
224}
danec6ffc12010-06-24 19:16:06 +0000225do_faultsim_test pagerfault-5.3 -faults oom-transient -prep {
dande4996e2010-06-19 11:30:41 +0000226 faultsim_restore_and_reopen
227 db func a_string a_string
228 file delete -force test2.db test2.db-journal test2.db-wal
229 execsql {
230 PRAGMA journal_mode = PERSIST;
231 ATTACH 'test2.db' AS aux;
232 PRAGMA aux.journal_mode = PERSIST;
233 PRAGMA aux.journal_size_limit = 0;
234 }
235} -body {
236 execsql {
237 BEGIN;
238 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
239 CREATE TABLE aux.t2 AS SELECT * FROM t1;
240 COMMIT;
241 }
242} -test {
243 faultsim_test_result {0 {}}
danec6ffc12010-06-24 19:16:06 +0000244 faultsim_integrity_check
245
246 set res ""
247 set rc [catch { set res [db one { PRAGMA aux.integrity_check }] }]
248 if {$rc!=0 || $res != "ok"} {error "integrity-check problem:$rc $res"}
dande4996e2010-06-19 11:30:41 +0000249}
250
dan153eda02010-06-21 07:45:47 +0000251#-------------------------------------------------------------------------
252# Test fault-injection as part of a commit when using
253# journal_mode=TRUNCATE.
254#
255do_test pagerfault-6-pre1 {
256 faultsim_delete_and_reopen
257 db func a_string a_string
258 execsql {
259 CREATE TABLE t1(a UNIQUE, b UNIQUE);
260 INSERT INTO t1 VALUES(a_string(200), a_string(300));
261 }
262 faultsim_save_and_close
263} {}
danf9b44192010-06-25 19:09:48 +0000264
dan153eda02010-06-21 07:45:47 +0000265do_faultsim_test pagerfault-6.1 -prep {
266 faultsim_restore_and_reopen
267 db func a_string a_string
268 execsql { PRAGMA journal_mode = TRUNCATE }
269} -body {
270 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
danf9b44192010-06-25 19:09:48 +0000271 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
272} -test {
273 faultsim_test_result {0 {}}
274 faultsim_integrity_check
275}
276
277# The unix vfs xAccess() method considers a file zero bytes in size to
278# "not exist". This proc overrides that behaviour so that a zero length
279# file is considered to exist.
280#
281proc xAccess {method filename op args} {
282 if {$op != "SQLITE_ACCESS_EXISTS"} { return "" }
283 return [file exists $filename]
284}
285do_faultsim_test pagerfault-6.2 -faults cantopen-* -prep {
286 shmfault filter xAccess
287 shmfault script xAccess
288
289 faultsim_restore_and_reopen
290 db func a_string a_string
291 execsql { PRAGMA journal_mode = TRUNCATE }
292} -body {
293 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
294 execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
dan153eda02010-06-21 07:45:47 +0000295} -test {
296 faultsim_test_result {0 {}}
297 faultsim_integrity_check
298}
299
dan146ed782010-06-19 17:26:37 +0000300# The following was an attempt to get a bitvec malloc to fail. Didn't work.
301#
302# do_test pagerfault-6-pre1 {
303# faultsim_delete_and_reopen
304# execsql {
305# CREATE TABLE t1(x, y, UNIQUE(x, y));
306# INSERT INTO t1 VALUES(1, randomblob(1501));
307# INSERT INTO t1 VALUES(2, randomblob(1502));
308# INSERT INTO t1 VALUES(3, randomblob(1503));
309# INSERT INTO t1 VALUES(4, randomblob(1504));
310# INSERT INTO t1
311# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
312# INSERT INTO t1
313# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
314# INSERT INTO t1
315# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
316# INSERT INTO t1
317# SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
318# }
319# faultsim_save_and_close
320# } {}
321# do_faultsim_test pagerfault-6 -prep {
322# faultsim_restore_and_reopen
323# } -body {
324# execsql {
325# BEGIN;
326# UPDATE t1 SET x=x+4 WHERE x=1;
327# SAVEPOINT one;
328# UPDATE t1 SET x=x+4 WHERE x=2;
329# SAVEPOINT three;
330# UPDATE t1 SET x=x+4 WHERE x=3;
331# SAVEPOINT four;
332# UPDATE t1 SET x=x+4 WHERE x=4;
333# RELEASE three;
334# COMMIT;
335# SELECT DISTINCT x FROM t1;
336# }
337# } -test {
338# faultsim_test_result {0 {5 6 7 8}}
339# faultsim_integrity_check
340# }
dan346e4262010-06-23 19:27:36 +0000341#
dandca321a2010-06-24 10:50:17 +0000342
343# This is designed to provoke a special case in the pager code:
344#
345# If an error (specifically, a FULL or IOERR error) occurs while writing a
346# dirty page to the file-system in order to free up memory, the pager enters
347# the "error state". An IO error causes SQLite to roll back the current
348# transaction (exiting the error state). A FULL error, however, may only
349# rollback the current statement.
350#
351# This block tests that nothing goes wrong if a FULL error occurs while
352# writing a dirty page out to free memory from within a statement that has
353# opened a statement transaction.
354#
dan346e4262010-06-23 19:27:36 +0000355do_test pagerfault-7-pre1 {
356 faultsim_delete_and_reopen
357 execsql {
358 CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
359 BEGIN;
360 INSERT INTO t2 VALUES(NULL, randomblob(1500));
361 INSERT INTO t2 VALUES(NULL, randomblob(1500));
362 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 4
363 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 8
364 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 16
365 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 32
366 INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2; -- 64
367 COMMIT;
368 CREATE TABLE t1(a PRIMARY KEY, b);
369 INSERT INTO t1 SELECT * FROM t2;
370 DROP TABLE t2;
371 }
372 faultsim_save_and_close
373} {}
danec6ffc12010-06-24 19:16:06 +0000374do_faultsim_test pagerfault-7 -prep {
dan346e4262010-06-23 19:27:36 +0000375 faultsim_restore_and_reopen
376 execsql {
377 PRAGMA cache_size = 10;
378 BEGIN;
379 UPDATE t1 SET b = randomblob(1500);
380 }
381} -body {
382 execsql { UPDATE t1 SET a = 65, b = randomblob(1500) WHERE (a+1)>200 }
383 execsql COMMIT
384} -test {
385 faultsim_test_result {0 {}}
386 faultsim_integrity_check
387}
dan146ed782010-06-19 17:26:37 +0000388
dandca321a2010-06-24 10:50:17 +0000389do_test pagerfault-8-pre1 {
390 faultsim_delete_and_reopen
391 execsql {
392 PRAGMA auto_vacuum = 1;
393 CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
394 BEGIN;
395 INSERT INTO t1 VALUES(NULL, randomblob(1500));
396 INSERT INTO t1 VALUES(NULL, randomblob(1500));
397 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 4
398 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 8
399 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 16
400 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 32
401 INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1; -- 64
402 COMMIT;
403 }
404 faultsim_save_and_close
405 set filesize [file size test.db]
406 set {} {}
407} {}
408do_test pagerfault-8-pre2 {
409 faultsim_restore_and_reopen
410 execsql { DELETE FROM t1 WHERE a>32 }
411 expr {[file size test.db] < $filesize}
412} {1}
dandca321a2010-06-24 10:50:17 +0000413do_faultsim_test pagerfault-8 -prep {
414 faultsim_restore_and_reopen
415 execsql {
416 BEGIN;
417 DELETE FROM t1 WHERE a>32;
418 }
419} -body {
420 execsql COMMIT
421} -test {
422 faultsim_test_result {0 {}}
423 faultsim_integrity_check
424}
425
dan273f3f02010-06-26 15:42:33 +0000426#-------------------------------------------------------------------------
427# This test case is specially designed so that during a savepoint
428# rollback, a new cache entry must be allocated (see comments surrounding
429# the call to sqlite3PagerAcquire() from within pager_playback_one_page()
430# for details). Test the effects of injecting an OOM at this point.
431#
dan0a6052e2010-06-24 13:24:26 +0000432do_test pagerfault-9-pre1 {
433 faultsim_delete_and_reopen
434 execsql {
435 PRAGMA auto_vacuum = incremental;
436 CREATE TABLE t1(x);
437 CREATE TABLE t2(y);
438 CREATE TABLE t3(z);
439
440 INSERT INTO t1 VALUES(randomblob(900));
441 INSERT INTO t1 VALUES(randomblob(900));
442 DELETE FROM t1;
443 }
444 faultsim_save_and_close
445} {}
dan273f3f02010-06-26 15:42:33 +0000446do_faultsim_test pagerfault-9.1 -prep {
dan0a6052e2010-06-24 13:24:26 +0000447 faultsim_restore_and_reopen
448 execsql {
449 BEGIN;
450 INSERT INTO t1 VALUES(randomblob(900));
451 INSERT INTO t1 VALUES(randomblob(900));
452 DROP TABLE t3;
453 DROP TABLE t2;
454 SAVEPOINT abc;
455 PRAGMA incremental_vacuum;
456 }
457} -body {
458 execsql {
459 ROLLBACK TO abc;
460 COMMIT;
461 PRAGMA freelist_count
462 }
463} -test {
464 faultsim_test_result {0 2}
465 faultsim_integrity_check
466
467 set sl [db one { SELECT COALESCE(sum(length(x)), 'null') FROM t1 }]
468 if {$sl!="null" && $sl!=1800} {
469 error "Content looks no good... ($sl)"
470 }
471}
472
dan273f3f02010-06-26 15:42:33 +0000473#-------------------------------------------------------------------------
474# Test fault injection with a temporary database file.
475#
danc8ce3972010-06-29 10:30:23 +0000476foreach v {a b} {
477 do_faultsim_test pagerfault-10$v -prep {
478 sqlite3 db ""
479 db func a_string a_string;
480 execsql {
481 PRAGMA cache_size = 10;
482 BEGIN;
483 CREATE TABLE xx(a, b, UNIQUE(a, b));
484 INSERT INTO xx VALUES(a_string(200), a_string(200));
485 INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
486 INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
487 INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
488 INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
489 COMMIT;
490 }
491 } -body {
492 execsql { UPDATE xx SET a = a_string(300) }
493 } -test {
494 faultsim_test_result {0 {}}
495 if {$::v == "b"} { execsql { PRAGMA journal_mode = TRUNCATE } }
496 faultsim_integrity_check
497 faultsim_integrity_check
dan273f3f02010-06-26 15:42:33 +0000498 }
dan273f3f02010-06-26 15:42:33 +0000499}
500
dan273f3f02010-06-26 15:42:33 +0000501#-------------------------------------------------------------------------
502# Test fault injection with transaction savepoints (savepoints created
503# when a SAVEPOINT command is executed outside of any other savepoint
504# or transaction context).
505#
506do_test pagerfault-9-pre1 {
507 faultsim_delete_and_reopen
508 db func a_string a_string;
509 execsql {
510 PRAGMA auto_vacuum = on;
511 CREATE TABLE t1(x UNIQUE);
512 CREATE TABLE t2(y UNIQUE);
513 CREATE TABLE t3(z UNIQUE);
514 BEGIN;
515 INSERT INTO t1 VALUES(a_string(202));
516 INSERT INTO t2 VALUES(a_string(203));
517 INSERT INTO t3 VALUES(a_string(204));
518 INSERT INTO t1 SELECT a_string(202) FROM t1;
519 INSERT INTO t1 SELECT a_string(203) FROM t1;
520 INSERT INTO t1 SELECT a_string(204) FROM t1;
521 INSERT INTO t1 SELECT a_string(205) FROM t1;
522 INSERT INTO t2 SELECT a_string(length(x)) FROM t1;
523 INSERT INTO t3 SELECT a_string(length(x)) FROM t1;
524 COMMIT;
525 }
526 faultsim_save_and_close
527} {}
528do_faultsim_test pagerfault-11 -prep {
529 faultsim_restore_and_reopen
530 execsql { PRAGMA cache_size = 10 }
531} -body {
532 execsql {
533 SAVEPOINT trans;
534 UPDATE t2 SET y = y||'2';
535 INSERT INTO t3 SELECT * FROM t2;
536 DELETE FROM t1;
537 ROLLBACK TO trans;
538 UPDATE t1 SET x = x||'3';
539 INSERT INTO t2 SELECT * FROM t1;
540 DELETE FROM t3;
541 RELEASE trans;
542 }
543} -test {
544 faultsim_test_result {0 {}}
545 faultsim_integrity_check
546}
547
danc8ce3972010-06-29 10:30:23 +0000548#-------------------------------------------------------------------------
549# Test fault injection when writing to a database file that resides on
550# a file-system with a sector-size larger than the database page-size.
551#
dand3533312010-06-28 19:04:02 +0000552do_test pagerfault-12-pre1 {
553 testvfs ss_layer -default 1
554 ss_layer sectorsize 4096
555 faultsim_delete_and_reopen
556 db func a_string a_string;
557
558 execsql {
559 PRAGMA page_size = 1024;
560 PRAGMA journal_mode = PERSIST;
561 PRAGMA cache_size = 10;
562 BEGIN;
563 CREATE TABLE t1(x, y UNIQUE);
564 INSERT INTO t1 VALUES(a_string(333), a_string(444));
565 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
566 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
567 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
568 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
569 INSERT INTO t1 SELECT a_string(44), a_string(55) FROM t1 LIMIT 13;
570 COMMIT;
571 }
572 faultsim_save_and_close
573} {}
574do_faultsim_test pagerfault-12 -prep {
575 faultsim_restore_and_reopen
576 execsql { PRAGMA cache_size = 10 }
577 db func a_string a_string;
578} -body {
579 execsql {
580 UPDATE t1 SET x = a_string(length(x)), y = a_string(length(y));
581 }
582} -test {
583 faultsim_test_result {0 {}}
584 faultsim_integrity_check
585}
586
587
danc8ce3972010-06-29 10:30:23 +0000588#-------------------------------------------------------------------------
danba3cbf32010-06-30 04:29:03 +0000589# Test fault injection when SQLite opens a database where the size of the
590# database file is zero bytes but the accompanying journal file is larger
591# than that. In this scenario SQLite should delete the journal file
592# without rolling it back, even if it is in all other respects a valid
593# hot-journal file.
danc8ce3972010-06-29 10:30:23 +0000594#
595do_test pagerfault-13-pre1 {
596 faultsim_delete_and_reopen
597 db func a_string a_string;
598 execsql {
599 PRAGMA journal_mode = PERSIST;
600 BEGIN;
601 CREATE TABLE t1(x, y UNIQUE);
602 INSERT INTO t1 VALUES(a_string(333), a_string(444));
603 COMMIT;
604 }
605 db close
606 file delete -force test.db
607 faultsim_save
608} {}
609do_faultsim_test pagerfault-13 -prep {
610 faultsim_restore_and_reopen
611} -body {
612 execsql { CREATE TABLE xx(a, b) }
613} -test {
614 faultsim_test_result {0 {}}
615}
616
dan6b63ab42010-06-30 10:36:18 +0000617
danba3cbf32010-06-30 04:29:03 +0000618#---------------------------------------------------------------------------
619# Test fault injection into a small backup operation.
620#
621do_test pagerfault-14-pre1 {
622 faultsim_delete_and_reopen
623 db func a_string a_string;
624 execsql {
625 PRAGMA journal_mode = PERSIST;
626 ATTACH 'test.db2' AS two;
627 BEGIN;
628 CREATE TABLE t1(x, y UNIQUE);
629 CREATE TABLE two.t2(x, y UNIQUE);
630 INSERT INTO t1 VALUES(a_string(333), a_string(444));
631 INSERT INTO t2 VALUES(a_string(333), a_string(444));
632 COMMIT;
633 }
634 faultsim_save_and_close
635} {}
dan6b63ab42010-06-30 10:36:18 +0000636
637do_faultsim_test pagerfault-14a -prep {
danba3cbf32010-06-30 04:29:03 +0000638 faultsim_restore_and_reopen
639} -body {
640 if {[catch {db backup test.db2} msg]} { error [regsub {.*: } $msg {}] }
641} -test {
642 faultsim_test_result {0 {}} {1 {}} {1 {SQL logic error or missing database}}
danc8ce3972010-06-29 10:30:23 +0000643}
dan6b63ab42010-06-30 10:36:18 +0000644do_faultsim_test pagerfault-14b -prep {
645 faultsim_restore_and_reopen
646 sqlite3 db2 ""
647 db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
648} -body {
649 sqlite3_backup B db2 main db main
650 B step 200
651 set rc [B finish]
652 if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
653 if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
654 set {} {}
655} -test {
656 faultsim_test_result {0 {}}
657}
danc8ce3972010-06-29 10:30:23 +0000658
danba3cbf32010-06-30 04:29:03 +0000659do_test pagerfault-15-pre1 {
660 faultsim_delete_and_reopen
661 db func a_string a_string;
662 execsql {
663 BEGIN;
664 CREATE TABLE t1(x, y UNIQUE);
665 INSERT INTO t1 VALUES(a_string(11), a_string(22));
666 INSERT INTO t1 VALUES(a_string(11), a_string(22));
667 COMMIT;
668 }
669 faultsim_save_and_close
670} {}
671do_faultsim_test pagerfault-15 -prep {
672 faultsim_restore_and_reopen
673 db func a_string a_string;
674} -body {
675 db eval { SELECT * FROM t1 LIMIT 1 } {
676 execsql {
677 BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
678 BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
679 }
680 }
681} -test {
682 faultsim_test_result {0 {}}
683 faultsim_integrity_check
684}
685
danba3cbf32010-06-30 04:29:03 +0000686
687do_test pagerfault-16-pre1 {
688 faultsim_delete_and_reopen
689 execsql { CREATE TABLE t1(x, y UNIQUE) }
690 faultsim_save_and_close
691} {}
692do_faultsim_test pagerfault-16 -prep {
693 faultsim_restore_and_reopen
694} -body {
695 execsql {
696 PRAGMA locking_mode = exclusive;
697 PRAGMA journal_mode = wal;
698 INSERT INTO t1 VALUES(1, 2);
699 INSERT INTO t1 VALUES(3, 4);
700 PRAGMA journal_mode = delete;
701 INSERT INTO t1 VALUES(4, 5);
702 PRAGMA journal_mode = wal;
703 INSERT INTO t1 VALUES(6, 7);
704 PRAGMA journal_mode = persist;
705 INSERT INTO t1 VALUES(8, 9);
706 }
707} -test {
708 faultsim_test_result {0 {exclusive wal delete wal persist}}
709 faultsim_integrity_check
710}
711
712
dan89ccf442010-07-01 15:09:47 +0000713#-------------------------------------------------------------------------
714# Test fault injection while changing into and out of WAL mode.
715#
716do_test pagerfault-17-pre1 {
717 faultsim_delete_and_reopen
718 execsql {
719 CREATE TABLE t1(a PRIMARY KEY, b);
720 INSERT INTO t1 VALUES(1862, 'Botha');
721 INSERT INTO t1 VALUES(1870, 'Smuts');
722 INSERT INTO t1 VALUES(1866, 'Hertzog');
723 }
724 faultsim_save_and_close
725} {}
726do_faultsim_test pagerfault-17a -prep {
727 faultsim_restore_and_reopen
728} -body {
729 execsql {
730 PRAGMA journal_mode = wal;
731 PRAGMA journal_mode = delete;
732 }
733} -test {
734 faultsim_test_result {0 {wal delete}}
735 faultsim_integrity_check
736}
737do_faultsim_test pagerfault-17b -prep {
738 faultsim_restore_and_reopen
739 execsql { PRAGMA synchronous = OFF }
740} -body {
741 execsql {
742 PRAGMA journal_mode = wal;
743 INSERT INTO t1 VALUES(22, 'Clarke');
744 PRAGMA journal_mode = delete;
745 }
746} -test {
747 faultsim_test_result {0 {wal delete}}
748 faultsim_integrity_check
749}
750do_faultsim_test pagerfault-17c -prep {
751 faultsim_restore_and_reopen
752 execsql {
753 PRAGMA locking_mode = exclusive;
754 PRAGMA journal_mode = wal;
755 }
756} -body {
757 execsql { PRAGMA journal_mode = delete }
758} -test {
759 faultsim_test_result {0 delete}
760 faultsim_integrity_check
761}
762do_faultsim_test pagerfault-17d -prep {
763 faultsim_restore_and_reopen
764 sqlite3 db2 test.db
765 execsql { PRAGMA journal_mode = delete }
766 execsql { PRAGMA journal_mode = wal }
767 execsql { INSERT INTO t1 VALUES(99, 'Bradman') } db2
768} -body {
769 execsql { PRAGMA journal_mode = delete }
770} -test {
771 faultsim_test_result {1 {database is locked}}
772 faultsim_integrity_check
773}
774do_faultsim_test pagerfault-17e -prep {
775 faultsim_restore_and_reopen
776 sqlite3 db2 test.db
777 execsql { PRAGMA journal_mode = delete }
778 execsql { PRAGMA journal_mode = wal }
779 set ::chan [launch_testfixture]
780 testfixture $::chan {
781 sqlite3 db test.db
782 db eval { INSERT INTO t1 VALUES(101, 'Latham') }
783 }
784 catch { testfixture $::chan sqlite_abort }
785 catch { close $::chan }
786} -body {
787 execsql { PRAGMA journal_mode = delete }
788} -test {
789 faultsim_test_result {0 delete}
790 faultsim_integrity_check
791}
792
793#-------------------------------------------------------------------------
794# Test fault-injection when changing from journal_mode=persist to
795# journal_mode=delete (this involves deleting the journal file).
796#
797do_test pagerfault-18-pre1 {
798 faultsim_delete_and_reopen
799 execsql {
800 CREATE TABLE qq(x);
801 INSERT INTO qq VALUES('Herbert');
802 INSERT INTO qq VALUES('Macalister');
803 INSERT INTO qq VALUES('Mackenzie');
804 INSERT INTO qq VALUES('Lilley');
805 INSERT INTO qq VALUES('Palmer');
806 }
807 faultsim_save_and_close
808} {}
809do_faultsim_test pagerfault-18 -prep {
810 faultsim_restore_and_reopen
811 execsql {
812 PRAGMA journal_mode = PERSIST;
813 INSERT INTO qq VALUES('Beatty');
814 }
815} -body {
816 execsql { PRAGMA journal_mode = delete }
817} -test {
818 faultsim_test_result {0 delete}
819 faultsim_integrity_check
820}
821
822}
823
824do_faultsim_test pagerfault-19a -prep {
825 sqlite3 db :memory:
826 db func a_string a_string
827 execsql {
828 PRAGMA auto_vacuum = FULL;
829 BEGIN;
830 CREATE TABLE t1(a, b);
831 INSERT INTO t1 VALUES(a_string(5000), a_string(6000));
832 COMMIT;
833 }
834} -body {
835 execsql {
836 CREATE TABLE t2(a, b);
837 INSERT INTO t2 SELECT * FROM t1;
838 DELETE FROM t1;
839 }
840} -test {
841 faultsim_test_result {0 {}}
842}
843
844do_test pagerfault-19-pre1 {
845 faultsim_delete_and_reopen
846 execsql {
847 PRAGMA auto_vacuum = FULL;
848 CREATE TABLE t1(x); INSERT INTO t1 VALUES(1);
849 CREATE TABLE t2(x); INSERT INTO t2 VALUES(2);
850 CREATE TABLE t3(x); INSERT INTO t3 VALUES(3);
851 CREATE TABLE t4(x); INSERT INTO t4 VALUES(4);
852 CREATE TABLE t5(x); INSERT INTO t5 VALUES(5);
853 CREATE TABLE t6(x); INSERT INTO t6 VALUES(6);
854 }
855 faultsim_save_and_close
856} {}
857do_faultsim_test pagerfault-19b -prep {
858 faultsim_restore_and_reopen
859} -body {
860 execsql {
861 BEGIN;
862 UPDATE t4 SET x = x+1;
863 UPDATE t6 SET x = x+1;
864 SAVEPOINT one;
865 UPDATE t3 SET x = x+1;
866 SAVEPOINT two;
867 DROP TABLE t2;
868 ROLLBACK TO one;
869 COMMIT;
870 SELECT * FROM t3;
871 SELECT * FROM t4;
872 SELECT * FROM t6;
873 }
874} -test {
875 faultsim_test_result {0 {3 5 7}}
876}
877
878do_test pagerfault-20-pre1 {
879 faultsim_delete_and_reopen
880 db func a_string a_string
881 execsql {
882 CREATE TABLE x1(x, y, z, PRIMARY KEY(y, z));
883 INSERT INTO x1 VALUES(a_string(400), a_string(500), a_string(600));
884 INSERT INTO x1 SELECT a_string(600), a_string(400), a_string(500) FROM x1;
885 INSERT INTO x1 SELECT a_string(500), a_string(600), a_string(400) FROM x1;
886 INSERT INTO x1 SELECT a_string(400), a_string(500), a_string(600) FROM x1;
887 INSERT INTO x1 SELECT a_string(600), a_string(400), a_string(500) FROM x1;
888 INSERT INTO x1 SELECT a_string(500), a_string(600), a_string(400) FROM x1;
889 INSERT INTO x1 SELECT a_string(400), a_string(500), a_string(600) FROM x1;
890 }
891 faultsim_save_and_close
892} {}
893do_faultsim_test pagerfault-20 -prep {
894 faultsim_restore_and_reopen
895 db func a_string a_string
896} -body {
897 execsql {
898 BEGIN;
899 UPDATE x1 SET z = a_string(300);
900 DELETE FROM x1 WHERE rowid<32;
901 COMMIT;
902 }
903} -test {
904 faultsim_test_result {0 {}}
905 faultsim_integrity_check
906 set nRow [db one {SELECT count(*) FROM x1}]
907 if {$nRow!=33 && $nRow!=64} {error "Wrong number of rows $nRow"}
908}
dan273f3f02010-06-26 15:42:33 +0000909
danb0ac3e32010-06-16 10:55:42 +0000910finish_test