File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / pagerfault.test
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 7 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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>