Annotation of embedaddon/sqlite3/test/pagerfault.test, revision 1.1

1.1     ! misho       1: # 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: 
        !            13: set testdir [file dirname $argv0]
        !            14: source $testdir/tester.tcl
        !            15: source $testdir/lock_common.tcl
        !            16: source $testdir/malloc_common.tcl
        !            17: 
        !            18: if {[permutation] == "inmemory_journal"} {
        !            19:   finish_test
        !            20:   return
        !            21: }
        !            22: 
        !            23: if {$::tcl_platform(platform)=="windows"} {
        !            24:   finish_test
        !            25:   return
        !            26: }
        !            27: 
        !            28: set a_string_counter 1
        !            29: proc a_string {n} {
        !            30:   global a_string_counter
        !            31:   incr a_string_counter
        !            32:   string range [string repeat "${a_string_counter}." $n] 1 $n
        !            33: }
        !            34: db func a_string a_string
        !            35: 
        !            36: #-------------------------------------------------------------------------
        !            37: # Test fault-injection while rolling back a hot-journal file.
        !            38: #
        !            39: do_test pagerfault-1-pre1 {
        !            40:   execsql {
        !            41:     PRAGMA journal_mode = DELETE;
        !            42:     PRAGMA cache_size = 10;
        !            43:     CREATE TABLE t1(a UNIQUE, b UNIQUE);
        !            44:     INSERT INTO t1 VALUES(a_string(200), a_string(300));
        !            45:     INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
        !            46:     INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
        !            47:     BEGIN;
        !            48:       INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
        !            49:       INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
        !            50:       INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
        !            51:       INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
        !            52:   }
        !            53:   faultsim_save_and_close
        !            54: } {}
        !            55: do_faultsim_test pagerfault-1 -prep {
        !            56:   faultsim_restore_and_reopen
        !            57: } -body {
        !            58:   execsql { SELECT count(*) FROM t1 }
        !            59: } -test {
        !            60:   faultsim_test_result {0 4} 
        !            61:   faultsim_integrity_check
        !            62:   if {[db one { SELECT count(*) FROM t1 }] != 4} {
        !            63:     error "Database content appears incorrect"
        !            64:   }
        !            65: }
        !            66: 
        !            67: #-------------------------------------------------------------------------
        !            68: # Test fault-injection while rolling back a hot-journal file with a 
        !            69: # page-size different from the current value stored on page 1 of the
        !            70: # database file.
        !            71: #
        !            72: do_test pagerfault-2-pre1 {
        !            73:   testvfs tv -default 1
        !            74:   tv filter xSync
        !            75:   tv script xSyncCb
        !            76:   proc xSyncCb {filename args} {
        !            77:     if {[string match *journal filename]==0} faultsim_save
        !            78:   }
        !            79:   faultsim_delete_and_reopen
        !            80:   execsql {
        !            81:     PRAGMA page_size = 4096;
        !            82:     BEGIN;
        !            83:       CREATE TABLE abc(a, b, c);
        !            84:       INSERT INTO abc VALUES('o', 't', 't'); 
        !            85:       INSERT INTO abc VALUES('f', 'f', 's'); 
        !            86:       INSERT INTO abc SELECT * FROM abc; -- 4
        !            87:       INSERT INTO abc SELECT * FROM abc; -- 8
        !            88:       INSERT INTO abc SELECT * FROM abc; -- 16
        !            89:       INSERT INTO abc SELECT * FROM abc; -- 32
        !            90:       INSERT INTO abc SELECT * FROM abc; -- 64
        !            91:       INSERT INTO abc SELECT * FROM abc; -- 128
        !            92:       INSERT INTO abc SELECT * FROM abc; -- 256
        !            93:     COMMIT;
        !            94:     PRAGMA page_size = 1024;
        !            95:     VACUUM;
        !            96:   }
        !            97:   db close
        !            98:   tv delete
        !            99: } {}
        !           100: do_faultsim_test pagerfault-2 -prep {
        !           101:   faultsim_restore_and_reopen
        !           102: } -body {
        !           103:   execsql { SELECT * FROM abc }
        !           104: } -test {
        !           105:   set answer [split [string repeat "ottffs" 128] ""]
        !           106:   faultsim_test_result [list 0 $answer]
        !           107:   faultsim_integrity_check
        !           108:   set res [db eval { SELECT * FROM abc }]
        !           109:   if {$res != $answer} { error "Database content appears incorrect ($res)" }
        !           110: } 
        !           111: 
        !           112: #-------------------------------------------------------------------------
        !           113: # Test fault-injection while rolling back hot-journals that were created
        !           114: # as part of a multi-file transaction.
        !           115: #
        !           116: do_test pagerfault-3-pre1 {
        !           117:   testvfs tstvfs -default 1
        !           118:   tstvfs filter xDelete
        !           119:   tstvfs script xDeleteCallback
        !           120: 
        !           121:   proc xDeleteCallback {method file args} {
        !           122:     set file [file tail $file]
        !           123:     if { [string match *mj* $file] } { faultsim_save }
        !           124:   }
        !           125: 
        !           126:   faultsim_delete_and_reopen
        !           127:   db func a_string a_string
        !           128: 
        !           129:   execsql {
        !           130:     ATTACH 'test.db2' AS aux;
        !           131:     PRAGMA journal_mode = DELETE;
        !           132:     PRAGMA main.cache_size = 10;
        !           133:     PRAGMA aux.cache_size = 10;
        !           134: 
        !           135:     CREATE TABLE t1(a UNIQUE, b UNIQUE);
        !           136:     CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
        !           137:     INSERT INTO t1 VALUES(a_string(200), a_string(300));
        !           138:     INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
        !           139:     INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
        !           140:     INSERT INTO t2 SELECT * FROM t1;
        !           141: 
        !           142:     BEGIN;
        !           143:       INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
        !           144:       INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
        !           145:       INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
        !           146:       INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
        !           147:       REPLACE INTO t2 SELECT * FROM t1;
        !           148:     COMMIT;
        !           149:   }
        !           150: 
        !           151:   db close
        !           152:   tstvfs delete
        !           153: } {}
        !           154: do_faultsim_test pagerfault-3 -prep {
        !           155:   faultsim_restore_and_reopen
        !           156: } -body {
        !           157:   execsql { 
        !           158:     ATTACH 'test.db2' AS aux;
        !           159:     SELECT count(*) FROM t2;
        !           160:     SELECT count(*) FROM t1;
        !           161:   }
        !           162: } -test {
        !           163:   faultsim_test_result {0 {4 4}} {1 {unable to open database: test.db2}}
        !           164:   faultsim_integrity_check
        !           165:   catchsql { ATTACH 'test.db2' AS aux }
        !           166:   if {[db one { SELECT count(*) FROM t1 }] != 4
        !           167:    || [db one { SELECT count(*) FROM t2 }] != 4
        !           168:   } {
        !           169:     error "Database content appears incorrect"
        !           170:   }
        !           171: }
        !           172: 
        !           173: #-------------------------------------------------------------------------
        !           174: # Test fault-injection as part of a vanilla, no-transaction, INSERT
        !           175: # statement.
        !           176: #
        !           177: do_faultsim_test pagerfault-4 -prep {
        !           178:   faultsim_delete_and_reopen
        !           179: } -body {
        !           180:   execsql { 
        !           181:     CREATE TABLE x(y);
        !           182:     INSERT INTO x VALUES('z');
        !           183:     SELECT * FROM x;
        !           184:   }
        !           185: } -test {
        !           186:   faultsim_test_result {0 z}
        !           187:   faultsim_integrity_check
        !           188: }
        !           189: 
        !           190: #-------------------------------------------------------------------------
        !           191: # Test fault-injection as part of a commit when using journal_mode=PERSIST.
        !           192: # Three different cases:
        !           193: #
        !           194: #    pagerfault-5.1: With no journal_size_limit configured.
        !           195: #    pagerfault-5.2: With a journal_size_limit configured.
        !           196: #    pagerfault-5.4: Multi-file transaction. One connection has a 
        !           197: #                    journal_size_limit of 0, the other has no limit.
        !           198: #
        !           199: do_test pagerfault-5-pre1 {
        !           200:   faultsim_delete_and_reopen
        !           201:   db func a_string a_string
        !           202:   execsql {
        !           203:     CREATE TABLE t1(a UNIQUE, b UNIQUE);
        !           204:     INSERT INTO t1 VALUES(a_string(200), a_string(300));
        !           205:     INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
        !           206:     INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
        !           207:   }
        !           208:   faultsim_save_and_close
        !           209: } {}
        !           210: do_faultsim_test pagerfault-5.1 -prep {
        !           211:   faultsim_restore_and_reopen
        !           212:   db func a_string a_string
        !           213:   execsql { PRAGMA journal_mode = PERSIST }
        !           214: } -body {
        !           215:   execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
        !           216: } -test {
        !           217:   faultsim_test_result {0 {}}
        !           218:   faultsim_integrity_check
        !           219: }
        !           220: do_faultsim_test pagerfault-5.2 -prep {
        !           221:   faultsim_restore_and_reopen
        !           222:   db func a_string a_string
        !           223:   execsql { 
        !           224:     PRAGMA journal_mode = PERSIST;
        !           225:     PRAGMA journal_size_limit = 2048;
        !           226:   }
        !           227: } -body {
        !           228:   execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
        !           229: } -test {
        !           230:   faultsim_test_result {0 {}}
        !           231:   faultsim_integrity_check
        !           232: }
        !           233: do_faultsim_test pagerfault-5.3 -faults oom-transient -prep {
        !           234:   faultsim_restore_and_reopen
        !           235:   db func a_string a_string
        !           236:   forcedelete test2.db test2.db-journal test2.db-wal
        !           237:   execsql { 
        !           238:     PRAGMA journal_mode = PERSIST;
        !           239:     ATTACH 'test2.db' AS aux;
        !           240:     PRAGMA aux.journal_mode = PERSIST;
        !           241:     PRAGMA aux.journal_size_limit = 0;
        !           242:   }
        !           243: } -body {
        !           244:   execsql {
        !           245:     BEGIN;
        !           246:       INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
        !           247:       CREATE TABLE aux.t2 AS SELECT * FROM t1;
        !           248:     COMMIT;
        !           249:   }
        !           250: } -test {
        !           251:   faultsim_test_result {0 {}}
        !           252: 
        !           253:   catchsql { COMMIT }
        !           254:   catchsql { ROLLBACK }
        !           255: 
        !           256:   faultsim_integrity_check
        !           257:   set res ""
        !           258:   set rc [catch { set res [db one { PRAGMA aux.integrity_check }] }]
        !           259:   if {$rc!=0 || $res != "ok"} {error "integrity-check problem:$rc $res"}
        !           260: }
        !           261: 
        !           262: #-------------------------------------------------------------------------
        !           263: # Test fault-injection as part of a commit when using 
        !           264: # journal_mode=TRUNCATE.
        !           265: #
        !           266: do_test pagerfault-6-pre1 {
        !           267:   faultsim_delete_and_reopen
        !           268:   db func a_string a_string
        !           269:   execsql {
        !           270:     CREATE TABLE t1(a UNIQUE, b UNIQUE);
        !           271:     INSERT INTO t1 VALUES(a_string(200), a_string(300));
        !           272:   }
        !           273:   faultsim_save_and_close
        !           274: } {}
        !           275: 
        !           276: do_faultsim_test pagerfault-6.1 -prep {
        !           277:   faultsim_restore_and_reopen
        !           278:   db func a_string a_string
        !           279:   execsql { PRAGMA journal_mode = TRUNCATE }
        !           280: } -body {
        !           281:   execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
        !           282:   execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
        !           283: } -test {
        !           284:   faultsim_test_result {0 {}}
        !           285:   faultsim_integrity_check
        !           286: }
        !           287: 
        !           288: # The unix vfs xAccess() method considers a file zero bytes in size to
        !           289: # "not exist". This proc overrides that behaviour so that a zero length
        !           290: # file is considered to exist.
        !           291: #
        !           292: proc xAccess {method filename op args} {
        !           293:   if {$op != "SQLITE_ACCESS_EXISTS"} { return "" }
        !           294:   return [file exists $filename]
        !           295: }
        !           296: do_faultsim_test pagerfault-6.2 -faults cantopen-* -prep {
        !           297:   shmfault filter xAccess
        !           298:   shmfault script xAccess
        !           299: 
        !           300:   faultsim_restore_and_reopen
        !           301:   db func a_string a_string
        !           302:   execsql { PRAGMA journal_mode = TRUNCATE }
        !           303: } -body {
        !           304:   execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
        !           305:   execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
        !           306: } -test {
        !           307:   faultsim_test_result {0 {}}
        !           308:   faultsim_integrity_check
        !           309: }
        !           310: 
        !           311: # The following was an attempt to get a bitvec malloc to fail. Didn't work.
        !           312: #
        !           313: # do_test pagerfault-6-pre1 {
        !           314: #   faultsim_delete_and_reopen
        !           315: #   execsql {
        !           316: #     CREATE TABLE t1(x, y, UNIQUE(x, y));
        !           317: #     INSERT INTO t1 VALUES(1, randomblob(1501));
        !           318: #     INSERT INTO t1 VALUES(2, randomblob(1502));
        !           319: #     INSERT INTO t1 VALUES(3, randomblob(1503));
        !           320: #     INSERT INTO t1 VALUES(4, randomblob(1504));
        !           321: #     INSERT INTO t1 
        !           322: #       SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
        !           323: #     INSERT INTO t1 
        !           324: #       SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
        !           325: #     INSERT INTO t1 
        !           326: #       SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
        !           327: #     INSERT INTO t1 
        !           328: #       SELECT x, randomblob(1500+oid+(SELECT max(oid) FROM t1)) FROM t1;
        !           329: #   }
        !           330: #   faultsim_save_and_close
        !           331: # } {}
        !           332: # do_faultsim_test pagerfault-6 -prep {
        !           333: #   faultsim_restore_and_reopen
        !           334: # } -body {
        !           335: #   execsql { 
        !           336: #     BEGIN;
        !           337: #       UPDATE t1 SET x=x+4 WHERE x=1;
        !           338: #       SAVEPOINT one;
        !           339: #         UPDATE t1 SET x=x+4 WHERE x=2;
        !           340: #         SAVEPOINT three;
        !           341: #           UPDATE t1 SET x=x+4 WHERE x=3;
        !           342: #           SAVEPOINT four;
        !           343: #             UPDATE t1 SET x=x+4 WHERE x=4;
        !           344: #         RELEASE three;
        !           345: #     COMMIT;
        !           346: #     SELECT DISTINCT x FROM t1;
        !           347: #   }
        !           348: # } -test {
        !           349: #   faultsim_test_result {0 {5 6 7 8}}
        !           350: #   faultsim_integrity_check
        !           351: # }
        !           352: #
        !           353: 
        !           354: # This is designed to provoke a special case in the pager code:
        !           355: #
        !           356: # If an error (specifically, a FULL or IOERR error) occurs while writing a
        !           357: # dirty page to the file-system in order to free up memory, the pager enters
        !           358: # the "error state". An IO error causes SQLite to roll back the current
        !           359: # transaction (exiting the error state). A FULL error, however, may only
        !           360: # rollback the current statement.
        !           361: #
        !           362: # This block tests that nothing goes wrong if a FULL error occurs while
        !           363: # writing a dirty page out to free memory from within a statement that has
        !           364: # opened a statement transaction.
        !           365: #
        !           366: do_test pagerfault-7-pre1 {
        !           367:   faultsim_delete_and_reopen
        !           368:   execsql {
        !           369:     CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
        !           370:     BEGIN;
        !           371:       INSERT INTO t2 VALUES(NULL, randomblob(1500));
        !           372:       INSERT INTO t2 VALUES(NULL, randomblob(1500));
        !           373:       INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    --  4
        !           374:       INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    --  8
        !           375:       INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    -- 16
        !           376:       INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    -- 32
        !           377:       INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    -- 64
        !           378:     COMMIT;
        !           379:     CREATE TABLE t1(a PRIMARY KEY, b);
        !           380:     INSERT INTO t1 SELECT * FROM t2;
        !           381:     DROP TABLE t2;
        !           382:   }
        !           383:   faultsim_save_and_close
        !           384: } {}
        !           385: do_faultsim_test pagerfault-7 -prep {
        !           386:   faultsim_restore_and_reopen
        !           387:   execsql { 
        !           388:     PRAGMA cache_size = 10;
        !           389:     BEGIN;
        !           390:       UPDATE t1 SET b = randomblob(1500);
        !           391:   }
        !           392: } -body {
        !           393:   execsql { UPDATE t1 SET a = 65, b = randomblob(1500) WHERE (a+1)>200 }
        !           394:   execsql COMMIT
        !           395: } -test {
        !           396:   faultsim_test_result {0 {}}
        !           397:   faultsim_integrity_check
        !           398: }
        !           399: 
        !           400: do_test pagerfault-8-pre1 {
        !           401:   faultsim_delete_and_reopen
        !           402:   execsql {
        !           403:     PRAGMA auto_vacuum = 1;
        !           404:     CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
        !           405:     BEGIN;
        !           406:       INSERT INTO t1 VALUES(NULL, randomblob(1500));
        !           407:       INSERT INTO t1 VALUES(NULL, randomblob(1500));
        !           408:       INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    --  4
        !           409:       INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    --  8
        !           410:       INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    -- 16
        !           411:       INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    -- 32
        !           412:       INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    -- 64
        !           413:     COMMIT;
        !           414:   }
        !           415:   faultsim_save_and_close
        !           416:   set filesize [file size test.db]
        !           417:   set {} {}
        !           418: } {}
        !           419: do_test pagerfault-8-pre2 {
        !           420:   faultsim_restore_and_reopen
        !           421:   execsql { DELETE FROM t1 WHERE a>32 }
        !           422:   expr {[file size test.db] < $filesize}
        !           423: } {1}
        !           424: do_faultsim_test pagerfault-8 -prep {
        !           425:   faultsim_restore_and_reopen
        !           426:   execsql { 
        !           427:     BEGIN;
        !           428:     DELETE FROM t1 WHERE a>32;
        !           429:   }
        !           430: } -body {
        !           431:   execsql COMMIT
        !           432: } -test {
        !           433:   faultsim_test_result {0 {}}
        !           434:   faultsim_integrity_check
        !           435: }
        !           436: 
        !           437: #-------------------------------------------------------------------------
        !           438: # This test case is specially designed so that during a savepoint 
        !           439: # rollback, a new cache entry must be allocated (see comments surrounding
        !           440: # the call to sqlite3PagerAcquire() from within pager_playback_one_page()
        !           441: # for details). Test the effects of injecting an OOM at this point.
        !           442: #
        !           443: do_test pagerfault-9-pre1 {
        !           444:   faultsim_delete_and_reopen
        !           445:   execsql {
        !           446:     PRAGMA auto_vacuum = incremental;
        !           447:     CREATE TABLE t1(x);
        !           448:     CREATE TABLE t2(y);
        !           449:     CREATE TABLE t3(z);
        !           450: 
        !           451:     INSERT INTO t1 VALUES(randomblob(900));
        !           452:     INSERT INTO t1 VALUES(randomblob(900));
        !           453:     DELETE FROM t1;
        !           454:   }
        !           455:   faultsim_save_and_close
        !           456: } {}
        !           457: do_faultsim_test pagerfault-9.1 -prep {
        !           458:   faultsim_restore_and_reopen
        !           459:   execsql { 
        !           460:     BEGIN;
        !           461:       INSERT INTO t1 VALUES(randomblob(900));
        !           462:       INSERT INTO t1 VALUES(randomblob(900));
        !           463:       DROP TABLE t3;
        !           464:       DROP TABLE t2;
        !           465:       SAVEPOINT abc;
        !           466:         PRAGMA incremental_vacuum;
        !           467:   }
        !           468: } -body {
        !           469:   execsql {
        !           470:     ROLLBACK TO abc;
        !           471:     COMMIT;
        !           472:     PRAGMA freelist_count
        !           473:   }
        !           474: } -test {
        !           475:   faultsim_test_result {0 2}
        !           476:   faultsim_integrity_check
        !           477: 
        !           478:   set sl [db one { SELECT COALESCE(sum(length(x)), 'null') FROM t1 }]
        !           479:   if {$sl!="null" && $sl!=1800} { 
        !           480:     error "Content looks no good... ($sl)" 
        !           481:   }
        !           482: }
        !           483: 
        !           484: #-------------------------------------------------------------------------
        !           485: # Test fault injection with a temporary database file.
        !           486: #
        !           487: foreach v {a b} {
        !           488:   do_faultsim_test pagerfault-10$v -prep {
        !           489:     sqlite3 db ""
        !           490:     db func a_string a_string;
        !           491:     execsql {
        !           492:       PRAGMA cache_size = 10;
        !           493:       BEGIN;
        !           494:         CREATE TABLE xx(a, b, UNIQUE(a, b));
        !           495:         INSERT INTO xx VALUES(a_string(200), a_string(200));
        !           496:         INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
        !           497:         INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
        !           498:         INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
        !           499:         INSERT INTO xx SELECT a_string(200), a_string(200) FROM xx;
        !           500:       COMMIT;
        !           501:     }
        !           502:   } -body {
        !           503:     execsql { UPDATE xx SET a = a_string(300) }
        !           504:   } -test {
        !           505:     faultsim_test_result {0 {}}
        !           506:     if {$::v == "b"} { execsql { PRAGMA journal_mode = TRUNCATE } }
        !           507:     faultsim_integrity_check
        !           508:     faultsim_integrity_check
        !           509:   }
        !           510: }
        !           511: 
        !           512: #-------------------------------------------------------------------------
        !           513: # Test fault injection with transaction savepoints (savepoints created
        !           514: # when a SAVEPOINT command is executed outside of any other savepoint
        !           515: # or transaction context).
        !           516: #
        !           517: do_test pagerfault-9-pre1 {
        !           518:   faultsim_delete_and_reopen
        !           519:   db func a_string a_string;
        !           520:   execsql {
        !           521:     PRAGMA auto_vacuum = on;
        !           522:     CREATE TABLE t1(x UNIQUE);
        !           523:     CREATE TABLE t2(y UNIQUE);
        !           524:     CREATE TABLE t3(z UNIQUE);
        !           525:     BEGIN;
        !           526:       INSERT INTO t1 VALUES(a_string(202));
        !           527:       INSERT INTO t2 VALUES(a_string(203));
        !           528:       INSERT INTO t3 VALUES(a_string(204));
        !           529:       INSERT INTO t1 SELECT a_string(202) FROM t1;
        !           530:       INSERT INTO t1 SELECT a_string(203) FROM t1;
        !           531:       INSERT INTO t1 SELECT a_string(204) FROM t1;
        !           532:       INSERT INTO t1 SELECT a_string(205) FROM t1;
        !           533:       INSERT INTO t2 SELECT a_string(length(x)) FROM t1;
        !           534:       INSERT INTO t3 SELECT a_string(length(x)) FROM t1;
        !           535:     COMMIT;
        !           536:   }
        !           537:   faultsim_save_and_close
        !           538: } {}
        !           539: do_faultsim_test pagerfault-11 -prep {
        !           540:   faultsim_restore_and_reopen
        !           541:   execsql { PRAGMA cache_size = 10 }
        !           542: } -body {
        !           543:   execsql {
        !           544:     SAVEPOINT trans;
        !           545:       UPDATE t2 SET y = y||'2';
        !           546:       INSERT INTO t3 SELECT * FROM t2;
        !           547:       DELETE FROM t1;
        !           548:     ROLLBACK TO trans;
        !           549:     UPDATE t1 SET x = x||'3';
        !           550:     INSERT INTO t2 SELECT * FROM t1;
        !           551:     DELETE FROM t3;
        !           552:     RELEASE trans;
        !           553:   }
        !           554: } -test {
        !           555:   faultsim_test_result {0 {}}
        !           556:   faultsim_integrity_check
        !           557: }
        !           558: 
        !           559: 
        !           560: #-------------------------------------------------------------------------
        !           561: # Test fault injection when writing to a database file that resides on
        !           562: # a file-system with a sector-size larger than the database page-size.
        !           563: #
        !           564: do_test pagerfault-12-pre1 {
        !           565:   testvfs ss_layer -default 1
        !           566:   ss_layer sectorsize 4096
        !           567:   faultsim_delete_and_reopen
        !           568:   db func a_string a_string;
        !           569: 
        !           570:   execsql {
        !           571:     PRAGMA page_size = 1024;
        !           572:     PRAGMA journal_mode = PERSIST;
        !           573:     PRAGMA cache_size = 10;
        !           574:     BEGIN;
        !           575:       CREATE TABLE t1(x, y UNIQUE);
        !           576:       INSERT INTO t1 VALUES(a_string(333), a_string(444));
        !           577:       INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
        !           578:       INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
        !           579:       INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
        !           580:       INSERT INTO t1 SELECT a_string(333+rowid), a_string(444+rowid) FROM t1;
        !           581:       INSERT INTO t1 SELECT a_string(44), a_string(55) FROM t1 LIMIT 13;
        !           582:     COMMIT;
        !           583:   }
        !           584:   faultsim_save_and_close
        !           585: } {}
        !           586: 
        !           587: do_faultsim_test pagerfault-12a -prep {
        !           588:   faultsim_restore_and_reopen
        !           589:   execsql { PRAGMA cache_size = 10 }
        !           590:   db func a_string a_string;
        !           591: } -body {
        !           592:   execsql {
        !           593:     UPDATE t1 SET x = a_string(length(x)), y = a_string(length(y));
        !           594:   }
        !           595: } -test {
        !           596:   faultsim_test_result {0 {}}
        !           597:   faultsim_integrity_check
        !           598: }
        !           599: 
        !           600: do_test pagerfault-12-pre2 {
        !           601:   faultsim_restore_and_reopen
        !           602:   execsql {
        !           603:     CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 10;
        !           604:   }
        !           605:   faultsim_save_and_close
        !           606: } {}
        !           607: do_faultsim_test pagerfault-12b -prep {
        !           608:   faultsim_restore_and_reopen
        !           609:   db func a_string a_string;
        !           610:   execsql { SELECT * FROM t1 }
        !           611: } -body {
        !           612:   set sql(1) { UPDATE t2 SET x = a_string(280) }
        !           613:   set sql(2) { UPDATE t1 SET x = a_string(280) WHERE rowid = 5 }
        !           614: 
        !           615:   db eval { SELECT rowid FROM t1 LIMIT 2 } { db eval $sql($rowid) }
        !           616: 
        !           617: } -test {
        !           618:   faultsim_test_result {0 {}}
        !           619:   faultsim_integrity_check
        !           620: }
        !           621: 
        !           622: catch { db close }
        !           623: ss_layer delete
        !           624: 
        !           625: 
        !           626: #-------------------------------------------------------------------------
        !           627: # Test fault injection when SQLite opens a database where the size of the
        !           628: # database file is zero bytes but the accompanying journal file is larger
        !           629: # than that. In this scenario SQLite should delete the journal file 
        !           630: # without rolling it back, even if it is in all other respects a valid
        !           631: # hot-journal file.
        !           632: #
        !           633: do_test pagerfault-13-pre1 {
        !           634:   faultsim_delete_and_reopen
        !           635:   db func a_string a_string;
        !           636:   execsql {
        !           637:     PRAGMA journal_mode = PERSIST;
        !           638:     BEGIN;
        !           639:       CREATE TABLE t1(x, y UNIQUE);
        !           640:       INSERT INTO t1 VALUES(a_string(333), a_string(444));
        !           641:     COMMIT;
        !           642:   }
        !           643:   db close
        !           644:   forcedelete test.db
        !           645:   faultsim_save
        !           646: } {}
        !           647: do_faultsim_test pagerfault-13 -prep {
        !           648:   faultsim_restore_and_reopen
        !           649: } -body {
        !           650:   execsql { CREATE TABLE xx(a, b) }
        !           651: } -test {
        !           652:   faultsim_test_result {0 {}}
        !           653: }
        !           654: 
        !           655: #---------------------------------------------------------------------------
        !           656: # Test fault injection into a small backup operation.
        !           657: #
        !           658: do_test pagerfault-14-pre1 {
        !           659:   faultsim_delete_and_reopen
        !           660:   db func a_string a_string;
        !           661:   execsql {
        !           662:     PRAGMA journal_mode = PERSIST;
        !           663:     ATTACH 'test.db2' AS two;
        !           664:     BEGIN;
        !           665:       CREATE TABLE t1(x, y UNIQUE);
        !           666:       CREATE TABLE two.t2(x, y UNIQUE);
        !           667:       INSERT INTO t1 VALUES(a_string(333), a_string(444));
        !           668:       INSERT INTO t2 VALUES(a_string(333), a_string(444));
        !           669:     COMMIT;
        !           670:   }
        !           671:   faultsim_save_and_close
        !           672: } {}
        !           673: 
        !           674: do_faultsim_test pagerfault-14a -prep {
        !           675:   faultsim_restore_and_reopen
        !           676: } -body {
        !           677:   if {[catch {db backup test.db2} msg]} { error [regsub {.*: } $msg {}] }
        !           678: } -test {
        !           679:   faultsim_test_result {0 {}} {1 {}} {1 {SQL logic error or missing database}}
        !           680: }
        !           681: 
        !           682: # If TEMP_STORE is 2 or greater, then the database [db2] will be created
        !           683: # as an in-memory database. This test will not work in that case, as it
        !           684: # is not possible to change the page-size of an in-memory database. Even
        !           685: # using the backup API.
        !           686: #
        !           687: if {$TEMP_STORE<2} {
        !           688:   do_faultsim_test pagerfault-14b -prep {
        !           689:     catch { db2 close }
        !           690:     faultsim_restore_and_reopen
        !           691:     sqlite3 db2 ""
        !           692:     db2 eval { PRAGMA page_size = 4096; CREATE TABLE xx(a) }
        !           693:   } -body {
        !           694:     sqlite3_backup B db2 main db main
        !           695:     B step 200
        !           696:     set rc [B finish]
        !           697:     if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
        !           698:     if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
        !           699:     set {} {}
        !           700:   } -test {
        !           701:     faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}}
        !           702:   }
        !           703: }
        !           704: 
        !           705: do_faultsim_test pagerfault-14c -prep {
        !           706:   catch { db2 close }
        !           707:   faultsim_restore_and_reopen
        !           708:   sqlite3 db2 test.db2
        !           709:   db2 eval { 
        !           710:     PRAGMA synchronous = off; 
        !           711:     PRAGMA page_size = 4096; 
        !           712:     CREATE TABLE xx(a);
        !           713:   }
        !           714: } -body {
        !           715:   sqlite3_backup B db2 main db main
        !           716:   B step 200
        !           717:   set rc [B finish]
        !           718:   if {[string match SQLITE_IOERR_* $rc]} {set rc SQLITE_IOERR}
        !           719:   if {$rc != "SQLITE_OK"} { error [sqlite3_test_errstr $rc] }
        !           720:   set {} {}
        !           721: } -test {
        !           722:   faultsim_test_result {0 {}} {1 {sqlite3_backup_init() failed}}
        !           723: }
        !           724: 
        !           725: do_test pagerfault-15-pre1 {
        !           726:   faultsim_delete_and_reopen
        !           727:   db func a_string a_string;
        !           728:   execsql {
        !           729:     BEGIN;
        !           730:       CREATE TABLE t1(x, y UNIQUE);
        !           731:       INSERT INTO t1 VALUES(a_string(11), a_string(22));
        !           732:       INSERT INTO t1 VALUES(a_string(11), a_string(22));
        !           733:     COMMIT;
        !           734:   }
        !           735:   faultsim_save_and_close
        !           736: } {}
        !           737: do_faultsim_test pagerfault-15 -prep {
        !           738:   faultsim_restore_and_reopen
        !           739:   db func a_string a_string;
        !           740: } -body {
        !           741:   db eval { SELECT * FROM t1 LIMIT 1 } {
        !           742:     execsql {
        !           743:       BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
        !           744:       BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
        !           745:     }
        !           746:   }
        !           747: } -test {
        !           748:   faultsim_test_result {0 {}}
        !           749:   faultsim_integrity_check
        !           750: }
        !           751: 
        !           752: 
        !           753: do_test pagerfault-16-pre1 {
        !           754:   faultsim_delete_and_reopen
        !           755:   execsql { CREATE TABLE t1(x, y UNIQUE) }
        !           756:   faultsim_save_and_close
        !           757: } {}
        !           758: do_faultsim_test pagerfault-16 -prep {
        !           759:   faultsim_restore_and_reopen
        !           760: } -body {
        !           761:   execsql {
        !           762:     PRAGMA locking_mode = exclusive;
        !           763:     PRAGMA journal_mode = wal;
        !           764:     INSERT INTO t1 VALUES(1, 2);
        !           765:     INSERT INTO t1 VALUES(3, 4);
        !           766:     PRAGMA journal_mode = delete;
        !           767:     INSERT INTO t1 VALUES(4, 5);
        !           768:     PRAGMA journal_mode = wal;
        !           769:     INSERT INTO t1 VALUES(6, 7);
        !           770:     PRAGMA journal_mode = persist;
        !           771:     INSERT INTO t1 VALUES(8, 9);
        !           772:   }
        !           773: } -test {
        !           774:   faultsim_test_result {0 {exclusive wal delete wal persist}}
        !           775:   faultsim_integrity_check
        !           776: }
        !           777: 
        !           778: 
        !           779: #-------------------------------------------------------------------------
        !           780: # Test fault injection while changing into and out of WAL mode.
        !           781: #
        !           782: do_test pagerfault-17-pre1 {
        !           783:   faultsim_delete_and_reopen
        !           784:   execsql {
        !           785:     CREATE TABLE t1(a PRIMARY KEY, b);
        !           786:     INSERT INTO t1 VALUES(1862, 'Botha');
        !           787:     INSERT INTO t1 VALUES(1870, 'Smuts');
        !           788:     INSERT INTO t1 VALUES(1866, 'Hertzog');
        !           789:   }
        !           790:   faultsim_save_and_close
        !           791: } {}
        !           792: do_faultsim_test pagerfault-17a -prep {
        !           793:   faultsim_restore_and_reopen
        !           794: } -body {
        !           795:   execsql {
        !           796:     PRAGMA journal_mode = wal;
        !           797:     PRAGMA journal_mode = delete;
        !           798:   }
        !           799: } -test {
        !           800:   faultsim_test_result {0 {wal delete}}
        !           801:   faultsim_integrity_check
        !           802: }
        !           803: do_faultsim_test pagerfault-17b -prep {
        !           804:   faultsim_restore_and_reopen
        !           805:   execsql { PRAGMA synchronous = OFF }
        !           806: } -body {
        !           807:   execsql {
        !           808:     PRAGMA journal_mode = wal;
        !           809:     INSERT INTO t1 VALUES(22, 'Clarke');
        !           810:     PRAGMA journal_mode = delete;
        !           811:   }
        !           812: } -test {
        !           813:   faultsim_test_result {0 {wal delete}}
        !           814:   faultsim_integrity_check
        !           815: }
        !           816: do_faultsim_test pagerfault-17c -prep {
        !           817:   faultsim_restore_and_reopen
        !           818:   execsql { 
        !           819:     PRAGMA locking_mode = exclusive;
        !           820:     PRAGMA journal_mode = wal;
        !           821:   }
        !           822: } -body {
        !           823:   execsql { PRAGMA journal_mode = delete }
        !           824: } -test {
        !           825:   faultsim_test_result {0 delete}
        !           826:   faultsim_integrity_check
        !           827: }
        !           828: do_faultsim_test pagerfault-17d -prep {
        !           829:   catch { db2 close }
        !           830:   faultsim_restore_and_reopen
        !           831:   sqlite3 db2 test.db
        !           832:   execsql { PRAGMA journal_mode = delete }
        !           833:   execsql { PRAGMA journal_mode = wal }
        !           834:   execsql { INSERT INTO t1 VALUES(99, 'Bradman') } db2
        !           835: } -body {
        !           836:   execsql { PRAGMA journal_mode = delete }
        !           837: } -test {
        !           838:   faultsim_test_result {1 {database is locked}}
        !           839:   faultsim_integrity_check
        !           840: }
        !           841: do_faultsim_test pagerfault-17e -prep {
        !           842:   catch { db2 close }
        !           843:   faultsim_restore_and_reopen
        !           844:   sqlite3 db2 test.db
        !           845:   execsql { PRAGMA journal_mode = delete }
        !           846:   execsql { PRAGMA journal_mode = wal }
        !           847:   set ::chan [launch_testfixture]
        !           848:   testfixture $::chan {
        !           849:     sqlite3 db test.db
        !           850:     db eval { INSERT INTO t1 VALUES(101, 'Latham') }
        !           851:   }
        !           852:   catch { testfixture $::chan sqlite_abort }
        !           853:   catch { close $::chan }
        !           854: } -body {
        !           855:   execsql { PRAGMA journal_mode = delete }
        !           856: } -test {
        !           857:   faultsim_test_result {0 delete}
        !           858:   faultsim_integrity_check
        !           859: }
        !           860: 
        !           861: #-------------------------------------------------------------------------
        !           862: # Test fault-injection when changing from journal_mode=persist to 
        !           863: # journal_mode=delete (this involves deleting the journal file).
        !           864: #
        !           865: do_test pagerfault-18-pre1 {
        !           866:   faultsim_delete_and_reopen
        !           867:   execsql {
        !           868:     CREATE TABLE qq(x);
        !           869:     INSERT INTO qq VALUES('Herbert');
        !           870:     INSERT INTO qq VALUES('Macalister');
        !           871:     INSERT INTO qq VALUES('Mackenzie');
        !           872:     INSERT INTO qq VALUES('Lilley');
        !           873:     INSERT INTO qq VALUES('Palmer');
        !           874:   }
        !           875:   faultsim_save_and_close
        !           876: } {}
        !           877: do_faultsim_test pagerfault-18 -prep {
        !           878:   faultsim_restore_and_reopen
        !           879:   execsql {
        !           880:     PRAGMA journal_mode = PERSIST;
        !           881:     INSERT INTO qq VALUES('Beatty');
        !           882:   }
        !           883: } -body {
        !           884:   execsql { PRAGMA journal_mode = delete }
        !           885: } -test {
        !           886:   faultsim_test_result {0 delete}
        !           887:   faultsim_integrity_check
        !           888: }
        !           889: 
        !           890: do_faultsim_test pagerfault-19a -prep {
        !           891:   sqlite3 db :memory:
        !           892:   db func a_string a_string
        !           893:   execsql {
        !           894:     PRAGMA auto_vacuum = FULL;
        !           895:     BEGIN;
        !           896:       CREATE TABLE t1(a, b);
        !           897:       INSERT INTO t1 VALUES(a_string(5000), a_string(6000));
        !           898:     COMMIT;
        !           899:   }
        !           900: } -body {
        !           901:   execsql { 
        !           902:     CREATE TABLE t2(a, b);
        !           903:     INSERT INTO t2 SELECT * FROM t1; 
        !           904:     DELETE FROM t1;
        !           905:   }
        !           906: } -test {
        !           907:   faultsim_test_result {0 {}}
        !           908: }
        !           909: 
        !           910: do_test pagerfault-19-pre1 {
        !           911:   faultsim_delete_and_reopen
        !           912:   execsql {
        !           913:     PRAGMA auto_vacuum = FULL;
        !           914:     CREATE TABLE t1(x); INSERT INTO t1 VALUES(1);
        !           915:     CREATE TABLE t2(x); INSERT INTO t2 VALUES(2);
        !           916:     CREATE TABLE t3(x); INSERT INTO t3 VALUES(3);
        !           917:     CREATE TABLE t4(x); INSERT INTO t4 VALUES(4);
        !           918:     CREATE TABLE t5(x); INSERT INTO t5 VALUES(5);
        !           919:     CREATE TABLE t6(x); INSERT INTO t6 VALUES(6);
        !           920:   }
        !           921:   faultsim_save_and_close
        !           922: } {}
        !           923: do_faultsim_test pagerfault-19b -prep {
        !           924:   faultsim_restore_and_reopen
        !           925: } -body {
        !           926:   execsql { 
        !           927:     BEGIN;
        !           928:       UPDATE t4 SET x = x+1;
        !           929:       UPDATE t6 SET x = x+1;
        !           930:       SAVEPOINT one;
        !           931:         UPDATE t3 SET x = x+1;
        !           932:         SAVEPOINT two;
        !           933:           DROP TABLE t2;
        !           934:       ROLLBACK TO one;
        !           935:     COMMIT;
        !           936:     SELECT * FROM t3;
        !           937:     SELECT * FROM t4;
        !           938:     SELECT * FROM t6;
        !           939:   }
        !           940: } -test {
        !           941:   faultsim_test_result {0 {3 5 7}}
        !           942: }
        !           943: 
        !           944: #-------------------------------------------------------------------------
        !           945: # This tests fault-injection in a special case in the auto-vacuum code.
        !           946: #
        !           947: do_test pagerfault-20-pre1 {
        !           948:   faultsim_delete_and_reopen
        !           949:   execsql {
        !           950:     PRAGMA cache_size = 10;
        !           951:     PRAGMA auto_vacuum = FULL;
        !           952:     CREATE TABLE t0(a, b);
        !           953:   }
        !           954:   faultsim_save_and_close
        !           955: } {}
        !           956: do_faultsim_test pagerfault-20 -prep {
        !           957:   faultsim_restore_and_reopen
        !           958: } -body {
        !           959:   execsql { 
        !           960:     BEGIN;
        !           961:       CREATE TABLE t1(a, b);
        !           962:       CREATE TABLE t2(a, b);
        !           963:       DROP TABLE t1;
        !           964:     COMMIT;
        !           965:   }
        !           966: } -test {
        !           967:   faultsim_test_result {0 {}}
        !           968: }
        !           969: 
        !           970: do_test pagerfault-21-pre1 {
        !           971:   faultsim_delete_and_reopen
        !           972:   execsql {
        !           973:     PRAGMA cache_size = 10;
        !           974:     CREATE TABLE t0(a PRIMARY KEY, b);
        !           975:     INSERT INTO t0 VALUES(1, 2);
        !           976:   }
        !           977:   faultsim_save_and_close
        !           978: } {}
        !           979: do_faultsim_test pagerfault-21 -prep {
        !           980:   faultsim_restore_and_reopen
        !           981: } -body {
        !           982:   db eval { SELECT * FROM t0 LIMIT 1 } {
        !           983:     db eval { INSERT INTO t0 SELECT a+1, b FROM t0 }
        !           984:     db eval { INSERT INTO t0 SELECT a+2, b FROM t0 }
        !           985:   }
        !           986: } -test {
        !           987:   faultsim_test_result {0 {}}
        !           988: }
        !           989: 
        !           990: 
        !           991: #-------------------------------------------------------------------------
        !           992: # Test fault-injection and rollback when the nReserve header value 
        !           993: # is non-zero.
        !           994: #
        !           995: do_test pagerfault-21-pre1 {
        !           996:   faultsim_delete_and_reopen
        !           997:   execsql {
        !           998:     PRAGMA page_size = 1024;
        !           999:     PRAGMA journal_mode = WAL;
        !          1000:     PRAGMA journal_mode = DELETE;
        !          1001:   }
        !          1002:   db close
        !          1003:   hexio_write test.db 20    10
        !          1004:   hexio_write test.db 105 03F0
        !          1005:   sqlite3 db test.db
        !          1006:   db func a_string a_string
        !          1007:   execsql {
        !          1008:     CREATE TABLE t0(a PRIMARY KEY, b UNIQUE);
        !          1009:     INSERT INTO t0 VALUES(a_string(222), a_string(333));
        !          1010:     INSERT INTO t0 VALUES(a_string(223), a_string(334));
        !          1011:     INSERT INTO t0 VALUES(a_string(224), a_string(335));
        !          1012:     INSERT INTO t0 VALUES(a_string(225), a_string(336));
        !          1013:   }
        !          1014:   faultsim_save_and_close
        !          1015: } {}
        !          1016: 
        !          1017: do_faultsim_test pagerfault-21 -prep {
        !          1018:   faultsim_restore_and_reopen
        !          1019: } -body {
        !          1020:   execsql { INSERT INTO t0 SELECT a||'x', b||'x' FROM t0 }
        !          1021: } -test {
        !          1022:   faultsim_test_result {0 {}}
        !          1023:   faultsim_integrity_check
        !          1024: }
        !          1025: ifcapable crashtest {
        !          1026:   faultsim_delete_and_reopen
        !          1027:   execsql {
        !          1028:     PRAGMA page_size = 1024;
        !          1029:     PRAGMA journal_mode = WAL;
        !          1030:     PRAGMA journal_mode = DELETE;
        !          1031:   }
        !          1032:   db close
        !          1033:   hexio_write test.db 20    10
        !          1034:   hexio_write test.db 105 03F0
        !          1035: 
        !          1036:   sqlite3 db test.db
        !          1037:   db func a_string a_string
        !          1038:   execsql {
        !          1039:     CREATE TABLE t0(a PRIMARY KEY, b UNIQUE);
        !          1040:     INSERT INTO t0 VALUES(a_string(222), a_string(333));
        !          1041:     INSERT INTO t0 VALUES(a_string(223), a_string(334));
        !          1042:   }
        !          1043:   faultsim_save_and_close
        !          1044: 
        !          1045:   for {set iTest 1} {$iTest<50} {incr iTest} {
        !          1046:     do_test pagerfault-21.crash.$iTest.1 {
        !          1047:       crashsql -delay 1 -file test.db -seed $iTest {
        !          1048:         BEGIN;
        !          1049:           CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
        !          1050:           INSERT INTO t1 SELECT a, b FROM t0;
        !          1051:         COMMIT;
        !          1052:       }
        !          1053:     } {1 {child process exited abnormally}}
        !          1054:     do_test pagerfault-22.$iTest.2 {
        !          1055:       sqlite3 db test.db
        !          1056:       execsql { PRAGMA integrity_check }
        !          1057:     } {ok}
        !          1058:     db close
        !          1059:   }
        !          1060: }
        !          1061: 
        !          1062: 
        !          1063: #-------------------------------------------------------------------------
        !          1064: # When a 3.7.0 client opens a write-transaction on a database file that
        !          1065: # has been appended to or truncated by a pre-370 client, it updates
        !          1066: # the db-size in the file header immediately. This test case provokes
        !          1067: # errors during that operation.
        !          1068: #
        !          1069: do_test pagerfault-22-pre1 {
        !          1070:   faultsim_delete_and_reopen
        !          1071:   db func a_string a_string
        !          1072:   execsql {
        !          1073:     PRAGMA page_size = 1024;
        !          1074:     PRAGMA auto_vacuum = 0;
        !          1075:     CREATE TABLE t1(a);
        !          1076:     CREATE INDEX i1 ON t1(a);
        !          1077:     INSERT INTO t1 VALUES(a_string(3000));
        !          1078:     CREATE TABLE t2(a);
        !          1079:     INSERT INTO t2 VALUES(1);
        !          1080:   }
        !          1081:   db close
        !          1082:   sql36231 { INSERT INTO t1 VALUES(a_string(3000)) }
        !          1083:   faultsim_save_and_close
        !          1084: } {}
        !          1085: do_faultsim_test pagerfault-22 -prep {
        !          1086:   faultsim_restore_and_reopen
        !          1087: } -body {
        !          1088:   execsql { INSERT INTO t2 VALUES(2) }
        !          1089:   execsql { SELECT * FROM t2 }
        !          1090: } -test {
        !          1091:   faultsim_test_result {0 {1 2}}
        !          1092:   faultsim_integrity_check
        !          1093: }
        !          1094: 
        !          1095: #-------------------------------------------------------------------------
        !          1096: # Provoke an OOM error during a commit of multi-file transaction. One of
        !          1097: # the databases written during the transaction is an in-memory database.
        !          1098: # This test causes rollback of the in-memory database after CommitPhaseOne()
        !          1099: # has successfully returned. i.e. the series of calls for the aborted commit 
        !          1100: # is:
        !          1101: #
        !          1102: #   PagerCommitPhaseOne(<in-memory-db>)   ->   SQLITE_OK
        !          1103: #   PagerCommitPhaseOne(<file-db>)        ->   SQLITE_IOERR
        !          1104: #   PagerRollback(<in-memory-db>)
        !          1105: #   PagerRollback(<file-db>)
        !          1106: #
        !          1107: do_faultsim_test pagerfault-23 -prep {
        !          1108:   sqlite3 db :memory:
        !          1109:   foreach f [glob -nocomplain test.db*] { forcedelete $f }
        !          1110:   db eval { 
        !          1111:     ATTACH 'test.db2' AS aux;
        !          1112:     CREATE TABLE t1(a, b);
        !          1113:     CREATE TABLE aux.t2(a, b);
        !          1114:   }
        !          1115: } -body {
        !          1116:   execsql { 
        !          1117:     BEGIN;
        !          1118:       INSERT INTO t1 VALUES(1,2);
        !          1119:       INSERT INTO t2 VALUES(3,4); 
        !          1120:     COMMIT;
        !          1121:   }
        !          1122: } -test {
        !          1123:   faultsim_test_result {0 {}}
        !          1124:   faultsim_integrity_check
        !          1125: }
        !          1126: 
        !          1127: do_faultsim_test pagerfault-24 -prep {
        !          1128:   faultsim_delete_and_reopen
        !          1129:   db eval { PRAGMA temp_store = file }
        !          1130:   execsql { CREATE TABLE x(a, b) }
        !          1131: } -body {
        !          1132:   execsql { CREATE TEMP TABLE t1(a, b) }
        !          1133: } -test {
        !          1134:   faultsim_test_result {0 {}} \
        !          1135:     {1 {unable to open a temporary database file for storing temporary tables}}
        !          1136:   set ic [db eval { PRAGMA temp.integrity_check }]
        !          1137:   if {$ic != "ok"} { error "Integrity check: $ic" }
        !          1138: }
        !          1139: 
        !          1140: proc lockrows {n} {
        !          1141:   if {$n==0} { return "" }
        !          1142:   db eval { SELECT * FROM t1 WHERE oid = $n } { 
        !          1143:     return [lockrows [expr {$n-1}]]
        !          1144:   }
        !          1145: }
        !          1146: 
        !          1147: 
        !          1148: do_test pagerfault-25-pre1 {
        !          1149:   faultsim_delete_and_reopen
        !          1150:   db func a_string a_string
        !          1151:   execsql {
        !          1152:     PRAGMA page_size = 1024;
        !          1153:     PRAGMA auto_vacuum = 0;
        !          1154:     CREATE TABLE t1(a);
        !          1155:     INSERT INTO t1 VALUES(a_string(500));
        !          1156:     INSERT INTO t1 SELECT a_string(500) FROM t1;
        !          1157:     INSERT INTO t1 SELECT a_string(500) FROM t1;
        !          1158:     INSERT INTO t1 SELECT a_string(500) FROM t1;
        !          1159:     INSERT INTO t1 SELECT a_string(500) FROM t1;
        !          1160:     INSERT INTO t1 SELECT a_string(500) FROM t1;
        !          1161:   }
        !          1162:   faultsim_save_and_close
        !          1163: } {}
        !          1164: do_faultsim_test pagerfault-25 -prep {
        !          1165:   faultsim_restore_and_reopen
        !          1166:   db func a_string a_string
        !          1167:   set ::channel [db incrblob -readonly t1 a 1]
        !          1168:   execsql { 
        !          1169:     PRAGMA cache_size = 10;
        !          1170:     BEGIN;
        !          1171:       INSERT INTO t1 VALUES(a_string(3000));
        !          1172:       INSERT INTO t1 VALUES(a_string(3000));
        !          1173:   }
        !          1174: } -body {
        !          1175:   lockrows 30
        !          1176: } -test {
        !          1177:   catch { lockrows 30 }
        !          1178:   catch { db eval COMMIT }
        !          1179:   close $::channel
        !          1180:   faultsim_test_result {0 {}} 
        !          1181: }
        !          1182: 
        !          1183: do_faultsim_test pagerfault-26 -prep {
        !          1184:   faultsim_delete_and_reopen
        !          1185:   execsql {
        !          1186:     PRAGMA page_size = 1024;
        !          1187:     PRAGMA journal_mode = truncate;
        !          1188:     PRAGMA auto_vacuum = full;
        !          1189:     PRAGMA locking_mode=exclusive;
        !          1190:     CREATE TABLE t1(a, b);
        !          1191:     INSERT INTO t1 VALUES(1, 2);
        !          1192:     PRAGMA page_size = 4096;
        !          1193:   }
        !          1194: } -body {
        !          1195:   execsql {
        !          1196:     VACUUM;
        !          1197:   }
        !          1198: } -test {
        !          1199:   faultsim_test_result {0 {}}
        !          1200: 
        !          1201:   set contents [db eval {SELECT * FROM t1}]
        !          1202:   if {$contents != "1 2"} { error "Bad database contents ($contents)" }
        !          1203: 
        !          1204:   set sz [file size test.db]
        !          1205:   if {$testrc!=0 && $sz!=1024*3 && $sz!=4096*3} { 
        !          1206:     error "Expected file size to be 3072 or 12288 bytes - actual size $sz bytes"
        !          1207:   }
        !          1208:   if {$testrc==0 && $sz!=4096*3} { 
        !          1209:     error "Expected file size to be 12288 bytes - actual size $sz bytes"
        !          1210:   }
        !          1211: } 
        !          1212: 
        !          1213: do_test pagerfault-27-pre {
        !          1214:   faultsim_delete_and_reopen
        !          1215:   db func a_string a_string
        !          1216:   execsql {
        !          1217:     PRAGMA page_size = 1024;
        !          1218:     CREATE TABLE t1(a, b);
        !          1219:     CREATE TABLE t2(a UNIQUE, b UNIQUE);
        !          1220:     INSERT INTO t2 VALUES( a_string(800), a_string(800) );
        !          1221:     INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
        !          1222:     INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
        !          1223:     INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
        !          1224:     INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
        !          1225:     INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
        !          1226:     INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
        !          1227:     INSERT INTO t1 VALUES (a_string(20000), a_string(20000));
        !          1228:   }
        !          1229:   faultsim_save_and_close
        !          1230: } {}
        !          1231: do_faultsim_test pagerfault-27 -faults ioerr-persistent -prep {
        !          1232:   faultsim_restore_and_reopen
        !          1233:   db func a_string a_string
        !          1234:   execsql { 
        !          1235:     PRAGMA cache_size = 10;
        !          1236:     BEGIN EXCLUSIVE;
        !          1237:   }
        !          1238:   set ::channel [db incrblob t1 a 1]
        !          1239: } -body {
        !          1240:   puts $::channel [string repeat abc 6000]
        !          1241:   flush $::channel
        !          1242: } -test {
        !          1243:   catchsql { UPDATE t2 SET a = a_string(800), b = a_string(800) }
        !          1244:   catch { close $::channel }
        !          1245:   catchsql { ROLLBACK }
        !          1246:   faultsim_integrity_check
        !          1247: }
        !          1248: 
        !          1249: finish_test
        !          1250: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>