Annotation of embedaddon/sqlite3/test/pagerfault.test, revision 1.1.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>