blob: 542bb30ce8bd0e8bf39cfe09940b1890db6e05aa [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
danba3cbf32010-06-30 04:29:03 +0000617#---------------------------------------------------------------------------
618# Test fault injection into a small backup operation.
619#
620do_test pagerfault-14-pre1 {
621 faultsim_delete_and_reopen
622 db func a_string a_string;
623 execsql {
624 PRAGMA journal_mode = PERSIST;
625 ATTACH 'test.db2' AS two;
626 BEGIN;
627 CREATE TABLE t1(x, y UNIQUE);
628 CREATE TABLE two.t2(x, y UNIQUE);
629 INSERT INTO t1 VALUES(a_string(333), a_string(444));
630 INSERT INTO t2 VALUES(a_string(333), a_string(444));
631 COMMIT;
632 }
633 faultsim_save_and_close
634} {}
dan6b63ab42010-06-30 10:36:18 +0000635
636do_faultsim_test pagerfault-14a -prep {
danba3cbf32010-06-30 04:29:03 +0000637 faultsim_restore_and_reopen
638} -body {
639 if {[catch {db backup test.db2} msg]} { error [regsub {.*: } $msg {}] }
640} -test {
641 faultsim_test_result {0 {}} {1 {}} {1 {SQL logic error or missing database}}
danc8ce3972010-06-29 10:30:23 +0000642}
dan6b63ab42010-06-30 10:36:18 +0000643do_faultsim_test pagerfault-14b -prep {
644 faultsim_restore_and_reopen
645 sqlite3 db2 ""
646 db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
647} -body {
648 sqlite3_backup B db2 main db main
649 B step 200
650 set rc [B finish]
651 if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
652 if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
653 set {} {}
654} -test {
655 faultsim_test_result {0 {}}
656}
dand0b0d4d2010-07-01 19:01:56 +0000657do_faultsim_test pagerfault-14c -prep {
658 faultsim_restore_and_reopen
659 sqlite3 db2 test.db2
660 db2 eval {
661 PRAGMA synchronous = off;
662 PRAGMA page_size = 4096;
663 CREATE TABLE xx(a);
664 }
665} -body {
666 sqlite3_backup B db2 main db main
667 B step 200
668 set rc [B finish]
669 if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
670 if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
671 set {} {}
672} -test {
673 faultsim_test_result {0 {}}
674}
danc8ce3972010-06-29 10:30:23 +0000675
danba3cbf32010-06-30 04:29:03 +0000676do_test pagerfault-15-pre1 {
677 faultsim_delete_and_reopen
678 db func a_string a_string;
679 execsql {
680 BEGIN;
681 CREATE TABLE t1(x, y UNIQUE);
682 INSERT INTO t1 VALUES(a_string(11), a_string(22));
683 INSERT INTO t1 VALUES(a_string(11), a_string(22));
684 COMMIT;
685 }
686 faultsim_save_and_close
687} {}
688do_faultsim_test pagerfault-15 -prep {
689 faultsim_restore_and_reopen
690 db func a_string a_string;
691} -body {
692 db eval { SELECT * FROM t1 LIMIT 1 } {
693 execsql {
694 BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
695 BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
696 }
697 }
698} -test {
699 faultsim_test_result {0 {}}
700 faultsim_integrity_check
701}
702
danba3cbf32010-06-30 04:29:03 +0000703
704do_test pagerfault-16-pre1 {
705 faultsim_delete_and_reopen
706 execsql { CREATE TABLE t1(x, y UNIQUE) }
707 faultsim_save_and_close
708} {}
709do_faultsim_test pagerfault-16 -prep {
710 faultsim_restore_and_reopen
711} -body {
712 execsql {
713 PRAGMA locking_mode = exclusive;
714 PRAGMA journal_mode = wal;
715 INSERT INTO t1 VALUES(1, 2);
716 INSERT INTO t1 VALUES(3, 4);
717 PRAGMA journal_mode = delete;
718 INSERT INTO t1 VALUES(4, 5);
719 PRAGMA journal_mode = wal;
720 INSERT INTO t1 VALUES(6, 7);
721 PRAGMA journal_mode = persist;
722 INSERT INTO t1 VALUES(8, 9);
723 }
724} -test {
725 faultsim_test_result {0 {exclusive wal delete wal persist}}
726 faultsim_integrity_check
727}
728
729
dan89ccf442010-07-01 15:09:47 +0000730#-------------------------------------------------------------------------
731# Test fault injection while changing into and out of WAL mode.
732#
733do_test pagerfault-17-pre1 {
734 faultsim_delete_and_reopen
735 execsql {
736 CREATE TABLE t1(a PRIMARY KEY, b);
737 INSERT INTO t1 VALUES(1862, 'Botha');
738 INSERT INTO t1 VALUES(1870, 'Smuts');
739 INSERT INTO t1 VALUES(1866, 'Hertzog');
740 }
741 faultsim_save_and_close
742} {}
743do_faultsim_test pagerfault-17a -prep {
744 faultsim_restore_and_reopen
745} -body {
746 execsql {
747 PRAGMA journal_mode = wal;
748 PRAGMA journal_mode = delete;
749 }
750} -test {
751 faultsim_test_result {0 {wal delete}}
752 faultsim_integrity_check
753}
754do_faultsim_test pagerfault-17b -prep {
755 faultsim_restore_and_reopen
756 execsql { PRAGMA synchronous = OFF }
757} -body {
758 execsql {
759 PRAGMA journal_mode = wal;
760 INSERT INTO t1 VALUES(22, 'Clarke');
761 PRAGMA journal_mode = delete;
762 }
763} -test {
764 faultsim_test_result {0 {wal delete}}
765 faultsim_integrity_check
766}
767do_faultsim_test pagerfault-17c -prep {
768 faultsim_restore_and_reopen
769 execsql {
770 PRAGMA locking_mode = exclusive;
771 PRAGMA journal_mode = wal;
772 }
773} -body {
774 execsql { PRAGMA journal_mode = delete }
775} -test {
776 faultsim_test_result {0 delete}
777 faultsim_integrity_check
778}
779do_faultsim_test pagerfault-17d -prep {
780 faultsim_restore_and_reopen
781 sqlite3 db2 test.db
782 execsql { PRAGMA journal_mode = delete }
783 execsql { PRAGMA journal_mode = wal }
784 execsql { INSERT INTO t1 VALUES(99, 'Bradman') } db2
785} -body {
786 execsql { PRAGMA journal_mode = delete }
787} -test {
788 faultsim_test_result {1 {database is locked}}
789 faultsim_integrity_check
790}
791do_faultsim_test pagerfault-17e -prep {
792 faultsim_restore_and_reopen
793 sqlite3 db2 test.db
794 execsql { PRAGMA journal_mode = delete }
795 execsql { PRAGMA journal_mode = wal }
796 set ::chan [launch_testfixture]
797 testfixture $::chan {
798 sqlite3 db test.db
799 db eval { INSERT INTO t1 VALUES(101, 'Latham') }
800 }
801 catch { testfixture $::chan sqlite_abort }
802 catch { close $::chan }
803} -body {
804 execsql { PRAGMA journal_mode = delete }
805} -test {
806 faultsim_test_result {0 delete}
807 faultsim_integrity_check
808}
809
810#-------------------------------------------------------------------------
811# Test fault-injection when changing from journal_mode=persist to
812# journal_mode=delete (this involves deleting the journal file).
813#
814do_test pagerfault-18-pre1 {
815 faultsim_delete_and_reopen
816 execsql {
817 CREATE TABLE qq(x);
818 INSERT INTO qq VALUES('Herbert');
819 INSERT INTO qq VALUES('Macalister');
820 INSERT INTO qq VALUES('Mackenzie');
821 INSERT INTO qq VALUES('Lilley');
822 INSERT INTO qq VALUES('Palmer');
823 }
824 faultsim_save_and_close
825} {}
826do_faultsim_test pagerfault-18 -prep {
827 faultsim_restore_and_reopen
828 execsql {
829 PRAGMA journal_mode = PERSIST;
830 INSERT INTO qq VALUES('Beatty');
831 }
832} -body {
833 execsql { PRAGMA journal_mode = delete }
834} -test {
835 faultsim_test_result {0 delete}
836 faultsim_integrity_check
837}
838
dan89ccf442010-07-01 15:09:47 +0000839do_faultsim_test pagerfault-19a -prep {
840 sqlite3 db :memory:
841 db func a_string a_string
842 execsql {
843 PRAGMA auto_vacuum = FULL;
844 BEGIN;
845 CREATE TABLE t1(a, b);
846 INSERT INTO t1 VALUES(a_string(5000), a_string(6000));
847 COMMIT;
848 }
849} -body {
850 execsql {
851 CREATE TABLE t2(a, b);
852 INSERT INTO t2 SELECT * FROM t1;
853 DELETE FROM t1;
854 }
855} -test {
856 faultsim_test_result {0 {}}
857}
858
859do_test pagerfault-19-pre1 {
860 faultsim_delete_and_reopen
861 execsql {
862 PRAGMA auto_vacuum = FULL;
863 CREATE TABLE t1(x); INSERT INTO t1 VALUES(1);
864 CREATE TABLE t2(x); INSERT INTO t2 VALUES(2);
865 CREATE TABLE t3(x); INSERT INTO t3 VALUES(3);
866 CREATE TABLE t4(x); INSERT INTO t4 VALUES(4);
867 CREATE TABLE t5(x); INSERT INTO t5 VALUES(5);
868 CREATE TABLE t6(x); INSERT INTO t6 VALUES(6);
869 }
870 faultsim_save_and_close
871} {}
872do_faultsim_test pagerfault-19b -prep {
873 faultsim_restore_and_reopen
874} -body {
875 execsql {
876 BEGIN;
877 UPDATE t4 SET x = x+1;
878 UPDATE t6 SET x = x+1;
879 SAVEPOINT one;
880 UPDATE t3 SET x = x+1;
881 SAVEPOINT two;
882 DROP TABLE t2;
883 ROLLBACK TO one;
884 COMMIT;
885 SELECT * FROM t3;
886 SELECT * FROM t4;
887 SELECT * FROM t6;
888 }
889} -test {
890 faultsim_test_result {0 {3 5 7}}
891}
892
dand0b0d4d2010-07-01 19:01:56 +0000893#-------------------------------------------------------------------------
894# This tests fault-injection in a special case in the auto-vacuum code.
895#
dan89ccf442010-07-01 15:09:47 +0000896do_test pagerfault-20-pre1 {
897 faultsim_delete_and_reopen
dan89ccf442010-07-01 15:09:47 +0000898 execsql {
dand0b0d4d2010-07-01 19:01:56 +0000899 PRAGMA cache_size = 10;
900 PRAGMA auto_vacuum = FULL;
901 CREATE TABLE t0(a, b);
dan89ccf442010-07-01 15:09:47 +0000902 }
903 faultsim_save_and_close
904} {}
905do_faultsim_test pagerfault-20 -prep {
906 faultsim_restore_and_reopen
dan89ccf442010-07-01 15:09:47 +0000907} -body {
908 execsql {
909 BEGIN;
dand0b0d4d2010-07-01 19:01:56 +0000910 CREATE TABLE t1(a, b);
911 CREATE TABLE t2(a, b);
912 DROP TABLE t1;
dan89ccf442010-07-01 15:09:47 +0000913 COMMIT;
914 }
915} -test {
916 faultsim_test_result {0 {}}
dan89ccf442010-07-01 15:09:47 +0000917}
dan273f3f02010-06-26 15:42:33 +0000918
dand0b0d4d2010-07-01 19:01:56 +0000919do_test pagerfault-21-pre1 {
920 faultsim_delete_and_reopen
921 execsql {
922 PRAGMA cache_size = 10;
923 CREATE TABLE t0(a PRIMARY KEY, b);
924 INSERT INTO t0 VALUES(1, 2);
925 }
926 faultsim_save_and_close
927} {}
928do_faultsim_test pagerfault-21 -prep {
929 faultsim_restore_and_reopen
930} -body {
931 db eval { SELECT * FROM t0 LIMIT 1 } {
932 db eval { INSERT INTO t0 SELECT a+1, b FROM t0 }
933 db eval { INSERT INTO t0 SELECT a+2, b FROM t0 }
934 }
935} -test {
936 faultsim_test_result {0 {}}
937}
938
939}
940
941
danb0ac3e32010-06-16 10:55:42 +0000942finish_test