blob: 75b21a796e1c9f7b1423397a25b17b395e534f28 [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
danc396d4a2010-07-02 11:27:43 +0000548}
549
550
danc8ce3972010-06-29 10:30:23 +0000551#-------------------------------------------------------------------------
552# Test fault injection when writing to a database file that resides on
553# a file-system with a sector-size larger than the database page-size.
554#
dand3533312010-06-28 19:04:02 +0000555do_test pagerfault-12-pre1 {
556 testvfs ss_layer -default 1
557 ss_layer sectorsize 4096
558 faultsim_delete_and_reopen
559 db func a_string a_string;
560
561 execsql {
562 PRAGMA page_size = 1024;
563 PRAGMA journal_mode = PERSIST;
564 PRAGMA cache_size = 10;
565 BEGIN;
566 CREATE TABLE t1(x, y UNIQUE);
567 INSERT INTO t1 VALUES(a_string(333), a_string(444));
568 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
569 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
570 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
571 INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
572 INSERT INTO t1 SELECT a_string(44), a_string(55) FROM t1 LIMIT 13;
573 COMMIT;
574 }
575 faultsim_save_and_close
576} {}
danc396d4a2010-07-02 11:27:43 +0000577
578do_faultsim_test pagerfault-12a -prep {
dand3533312010-06-28 19:04:02 +0000579 faultsim_restore_and_reopen
580 execsql { PRAGMA cache_size = 10 }
581 db func a_string a_string;
582} -body {
583 execsql {
584 UPDATE t1 SET x = a_string(length(x)), y = a_string(length(y));
585 }
586} -test {
587 faultsim_test_result {0 {}}
588 faultsim_integrity_check
589}
590
danc396d4a2010-07-02 11:27:43 +0000591do_test pagerfault-12-pre2 {
592 faultsim_restore_and_reopen
593 execsql {
594 CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 10;
595 }
596 faultsim_save_and_close
597} {}
598do_faultsim_test pagerfault-12b -prep {
599 faultsim_restore_and_reopen
600 db func a_string a_string;
601 execsql { SELECT * FROM t1 }
602} -body {
603 set sql(1) { UPDATE t2 SET x = a_string(280) }
604 set sql(2) { UPDATE t1 SET x = a_string(280) WHERE rowid = 5 }
605
606 db eval { SELECT rowid FROM t1 LIMIT 2 } { db eval $sql($rowid) }
607
608} -test {
609 faultsim_test_result {0 {}}
610 faultsim_integrity_check
611}
612
613catch { db close }
614ss_layer delete
615
dand3533312010-06-28 19:04:02 +0000616
danc8ce3972010-06-29 10:30:23 +0000617#-------------------------------------------------------------------------
danba3cbf32010-06-30 04:29:03 +0000618# Test fault injection when SQLite opens a database where the size of the
619# database file is zero bytes but the accompanying journal file is larger
620# than that. In this scenario SQLite should delete the journal file
621# without rolling it back, even if it is in all other respects a valid
622# hot-journal file.
danc8ce3972010-06-29 10:30:23 +0000623#
624do_test pagerfault-13-pre1 {
625 faultsim_delete_and_reopen
626 db func a_string a_string;
627 execsql {
628 PRAGMA journal_mode = PERSIST;
629 BEGIN;
630 CREATE TABLE t1(x, y UNIQUE);
631 INSERT INTO t1 VALUES(a_string(333), a_string(444));
632 COMMIT;
633 }
634 db close
635 file delete -force test.db
636 faultsim_save
637} {}
638do_faultsim_test pagerfault-13 -prep {
639 faultsim_restore_and_reopen
640} -body {
641 execsql { CREATE TABLE xx(a, b) }
642} -test {
643 faultsim_test_result {0 {}}
644}
645
danba3cbf32010-06-30 04:29:03 +0000646#---------------------------------------------------------------------------
647# Test fault injection into a small backup operation.
648#
649do_test pagerfault-14-pre1 {
650 faultsim_delete_and_reopen
651 db func a_string a_string;
652 execsql {
653 PRAGMA journal_mode = PERSIST;
654 ATTACH 'test.db2' AS two;
655 BEGIN;
656 CREATE TABLE t1(x, y UNIQUE);
657 CREATE TABLE two.t2(x, y UNIQUE);
658 INSERT INTO t1 VALUES(a_string(333), a_string(444));
659 INSERT INTO t2 VALUES(a_string(333), a_string(444));
660 COMMIT;
661 }
662 faultsim_save_and_close
663} {}
dan6b63ab42010-06-30 10:36:18 +0000664
665do_faultsim_test pagerfault-14a -prep {
danba3cbf32010-06-30 04:29:03 +0000666 faultsim_restore_and_reopen
667} -body {
668 if {[catch {db backup test.db2} msg]} { error [regsub {.*: } $msg {}] }
669} -test {
670 faultsim_test_result {0 {}} {1 {}} {1 {SQL logic error or missing database}}
danc8ce3972010-06-29 10:30:23 +0000671}
dan6b63ab42010-06-30 10:36:18 +0000672do_faultsim_test pagerfault-14b -prep {
673 faultsim_restore_and_reopen
674 sqlite3 db2 ""
675 db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
676} -body {
677 sqlite3_backup B db2 main db main
678 B step 200
679 set rc [B finish]
680 if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
681 if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
682 set {} {}
683} -test {
684 faultsim_test_result {0 {}}
685}
dand0b0d4d2010-07-01 19:01:56 +0000686do_faultsim_test pagerfault-14c -prep {
687 faultsim_restore_and_reopen
688 sqlite3 db2 test.db2
689 db2 eval {
690 PRAGMA synchronous = off;
691 PRAGMA page_size = 4096;
692 CREATE TABLE xx(a);
693 }
694} -body {
695 sqlite3_backup B db2 main db main
696 B step 200
697 set rc [B finish]
698 if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
699 if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
700 set {} {}
701} -test {
702 faultsim_test_result {0 {}}
703}
danc8ce3972010-06-29 10:30:23 +0000704
danba3cbf32010-06-30 04:29:03 +0000705do_test pagerfault-15-pre1 {
706 faultsim_delete_and_reopen
707 db func a_string a_string;
708 execsql {
709 BEGIN;
710 CREATE TABLE t1(x, y UNIQUE);
711 INSERT INTO t1 VALUES(a_string(11), a_string(22));
712 INSERT INTO t1 VALUES(a_string(11), a_string(22));
713 COMMIT;
714 }
715 faultsim_save_and_close
716} {}
717do_faultsim_test pagerfault-15 -prep {
718 faultsim_restore_and_reopen
719 db func a_string a_string;
720} -body {
721 db eval { SELECT * FROM t1 LIMIT 1 } {
722 execsql {
723 BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
724 BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
725 }
726 }
727} -test {
728 faultsim_test_result {0 {}}
729 faultsim_integrity_check
730}
731
danba3cbf32010-06-30 04:29:03 +0000732
733do_test pagerfault-16-pre1 {
734 faultsim_delete_and_reopen
735 execsql { CREATE TABLE t1(x, y UNIQUE) }
736 faultsim_save_and_close
737} {}
738do_faultsim_test pagerfault-16 -prep {
739 faultsim_restore_and_reopen
740} -body {
741 execsql {
742 PRAGMA locking_mode = exclusive;
743 PRAGMA journal_mode = wal;
744 INSERT INTO t1 VALUES(1, 2);
745 INSERT INTO t1 VALUES(3, 4);
746 PRAGMA journal_mode = delete;
747 INSERT INTO t1 VALUES(4, 5);
748 PRAGMA journal_mode = wal;
749 INSERT INTO t1 VALUES(6, 7);
750 PRAGMA journal_mode = persist;
751 INSERT INTO t1 VALUES(8, 9);
752 }
753} -test {
754 faultsim_test_result {0 {exclusive wal delete wal persist}}
755 faultsim_integrity_check
756}
757
758
dan89ccf442010-07-01 15:09:47 +0000759#-------------------------------------------------------------------------
760# Test fault injection while changing into and out of WAL mode.
761#
762do_test pagerfault-17-pre1 {
763 faultsim_delete_and_reopen
764 execsql {
765 CREATE TABLE t1(a PRIMARY KEY, b);
766 INSERT INTO t1 VALUES(1862, 'Botha');
767 INSERT INTO t1 VALUES(1870, 'Smuts');
768 INSERT INTO t1 VALUES(1866, 'Hertzog');
769 }
770 faultsim_save_and_close
771} {}
772do_faultsim_test pagerfault-17a -prep {
773 faultsim_restore_and_reopen
774} -body {
775 execsql {
776 PRAGMA journal_mode = wal;
777 PRAGMA journal_mode = delete;
778 }
779} -test {
780 faultsim_test_result {0 {wal delete}}
781 faultsim_integrity_check
782}
783do_faultsim_test pagerfault-17b -prep {
784 faultsim_restore_and_reopen
785 execsql { PRAGMA synchronous = OFF }
786} -body {
787 execsql {
788 PRAGMA journal_mode = wal;
789 INSERT INTO t1 VALUES(22, 'Clarke');
790 PRAGMA journal_mode = delete;
791 }
792} -test {
793 faultsim_test_result {0 {wal delete}}
794 faultsim_integrity_check
795}
796do_faultsim_test pagerfault-17c -prep {
797 faultsim_restore_and_reopen
798 execsql {
799 PRAGMA locking_mode = exclusive;
800 PRAGMA journal_mode = wal;
801 }
802} -body {
803 execsql { PRAGMA journal_mode = delete }
804} -test {
805 faultsim_test_result {0 delete}
806 faultsim_integrity_check
807}
808do_faultsim_test pagerfault-17d -prep {
809 faultsim_restore_and_reopen
810 sqlite3 db2 test.db
811 execsql { PRAGMA journal_mode = delete }
812 execsql { PRAGMA journal_mode = wal }
813 execsql { INSERT INTO t1 VALUES(99, 'Bradman') } db2
814} -body {
815 execsql { PRAGMA journal_mode = delete }
816} -test {
817 faultsim_test_result {1 {database is locked}}
818 faultsim_integrity_check
819}
820do_faultsim_test pagerfault-17e -prep {
821 faultsim_restore_and_reopen
822 sqlite3 db2 test.db
823 execsql { PRAGMA journal_mode = delete }
824 execsql { PRAGMA journal_mode = wal }
825 set ::chan [launch_testfixture]
826 testfixture $::chan {
827 sqlite3 db test.db
828 db eval { INSERT INTO t1 VALUES(101, 'Latham') }
829 }
830 catch { testfixture $::chan sqlite_abort }
831 catch { close $::chan }
832} -body {
833 execsql { PRAGMA journal_mode = delete }
834} -test {
835 faultsim_test_result {0 delete}
836 faultsim_integrity_check
837}
838
839#-------------------------------------------------------------------------
840# Test fault-injection when changing from journal_mode=persist to
841# journal_mode=delete (this involves deleting the journal file).
842#
843do_test pagerfault-18-pre1 {
844 faultsim_delete_and_reopen
845 execsql {
846 CREATE TABLE qq(x);
847 INSERT INTO qq VALUES('Herbert');
848 INSERT INTO qq VALUES('Macalister');
849 INSERT INTO qq VALUES('Mackenzie');
850 INSERT INTO qq VALUES('Lilley');
851 INSERT INTO qq VALUES('Palmer');
852 }
853 faultsim_save_and_close
854} {}
855do_faultsim_test pagerfault-18 -prep {
856 faultsim_restore_and_reopen
857 execsql {
858 PRAGMA journal_mode = PERSIST;
859 INSERT INTO qq VALUES('Beatty');
860 }
861} -body {
862 execsql { PRAGMA journal_mode = delete }
863} -test {
864 faultsim_test_result {0 delete}
865 faultsim_integrity_check
866}
867
dan89ccf442010-07-01 15:09:47 +0000868do_faultsim_test pagerfault-19a -prep {
869 sqlite3 db :memory:
870 db func a_string a_string
871 execsql {
872 PRAGMA auto_vacuum = FULL;
873 BEGIN;
874 CREATE TABLE t1(a, b);
875 INSERT INTO t1 VALUES(a_string(5000), a_string(6000));
876 COMMIT;
877 }
878} -body {
879 execsql {
880 CREATE TABLE t2(a, b);
881 INSERT INTO t2 SELECT * FROM t1;
882 DELETE FROM t1;
883 }
884} -test {
885 faultsim_test_result {0 {}}
886}
887
888do_test pagerfault-19-pre1 {
889 faultsim_delete_and_reopen
890 execsql {
891 PRAGMA auto_vacuum = FULL;
892 CREATE TABLE t1(x); INSERT INTO t1 VALUES(1);
893 CREATE TABLE t2(x); INSERT INTO t2 VALUES(2);
894 CREATE TABLE t3(x); INSERT INTO t3 VALUES(3);
895 CREATE TABLE t4(x); INSERT INTO t4 VALUES(4);
896 CREATE TABLE t5(x); INSERT INTO t5 VALUES(5);
897 CREATE TABLE t6(x); INSERT INTO t6 VALUES(6);
898 }
899 faultsim_save_and_close
900} {}
901do_faultsim_test pagerfault-19b -prep {
902 faultsim_restore_and_reopen
903} -body {
904 execsql {
905 BEGIN;
906 UPDATE t4 SET x = x+1;
907 UPDATE t6 SET x = x+1;
908 SAVEPOINT one;
909 UPDATE t3 SET x = x+1;
910 SAVEPOINT two;
911 DROP TABLE t2;
912 ROLLBACK TO one;
913 COMMIT;
914 SELECT * FROM t3;
915 SELECT * FROM t4;
916 SELECT * FROM t6;
917 }
918} -test {
919 faultsim_test_result {0 {3 5 7}}
920}
921
dand0b0d4d2010-07-01 19:01:56 +0000922#-------------------------------------------------------------------------
923# This tests fault-injection in a special case in the auto-vacuum code.
924#
dan89ccf442010-07-01 15:09:47 +0000925do_test pagerfault-20-pre1 {
926 faultsim_delete_and_reopen
dan89ccf442010-07-01 15:09:47 +0000927 execsql {
dand0b0d4d2010-07-01 19:01:56 +0000928 PRAGMA cache_size = 10;
929 PRAGMA auto_vacuum = FULL;
930 CREATE TABLE t0(a, b);
dan89ccf442010-07-01 15:09:47 +0000931 }
932 faultsim_save_and_close
933} {}
934do_faultsim_test pagerfault-20 -prep {
935 faultsim_restore_and_reopen
dan89ccf442010-07-01 15:09:47 +0000936} -body {
937 execsql {
938 BEGIN;
dand0b0d4d2010-07-01 19:01:56 +0000939 CREATE TABLE t1(a, b);
940 CREATE TABLE t2(a, b);
941 DROP TABLE t1;
dan89ccf442010-07-01 15:09:47 +0000942 COMMIT;
943 }
944} -test {
945 faultsim_test_result {0 {}}
dan89ccf442010-07-01 15:09:47 +0000946}
dan273f3f02010-06-26 15:42:33 +0000947
dand0b0d4d2010-07-01 19:01:56 +0000948do_test pagerfault-21-pre1 {
949 faultsim_delete_and_reopen
950 execsql {
951 PRAGMA cache_size = 10;
952 CREATE TABLE t0(a PRIMARY KEY, b);
953 INSERT INTO t0 VALUES(1, 2);
954 }
955 faultsim_save_and_close
956} {}
957do_faultsim_test pagerfault-21 -prep {
958 faultsim_restore_and_reopen
959} -body {
960 db eval { SELECT * FROM t0 LIMIT 1 } {
961 db eval { INSERT INTO t0 SELECT a+1, b FROM t0 }
962 db eval { INSERT INTO t0 SELECT a+2, b FROM t0 }
963 }
964} -test {
965 faultsim_test_result {0 {}}
966}
967
dand0b0d4d2010-07-01 19:01:56 +0000968
danb0ac3e32010-06-16 10:55:42 +0000969finish_test