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

1.1     ! misho       1: # 2011 August 08
        !             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: ifcapable !mergesort {
        !            19:   finish_test
        !            20:   return
        !            21: }
        !            22: 
        !            23: set testprefix indexfault
        !            24: 
        !            25: # Set up the custom fault-injector. This is further configured by using
        !            26: # different values for $::custom_filter and different implementations
        !            27: # of Tcl proc [xCustom] for each test case.
        !            28: #
        !            29: proc install_custom_faultsim {} {
        !            30:   set ::FAULTSIM(custom)            [list      \
        !            31:     -injectinstall   custom_injectinstall    \
        !            32:     -injectstart     custom_injectstart      \
        !            33:     -injectstop      custom_injectstop       \
        !            34:     -injecterrlist   {{1 {disk I/O error}}}  \
        !            35:     -injectuninstall custom_injectuninstall  \
        !            36:   ]
        !            37:   proc custom_injectinstall {} {
        !            38:     testvfs shmfault -default true
        !            39:     shmfault filter $::custom_filter
        !            40:     shmfault script xCustom
        !            41:   }
        !            42:   proc custom_injectuninstall {} {
        !            43:     catch {db  close}
        !            44:     catch {db2 close}
        !            45:     shmfault delete
        !            46:   }
        !            47:   set ::custom_ifail -1
        !            48:   set ::custom_nfail -1
        !            49:   proc custom_injectstart {iFail} {
        !            50:     set ::custom_ifail $iFail
        !            51:     set ::custom_nfail 0
        !            52:   }
        !            53:   proc custom_injectstop {} {
        !            54:     set ::custom_ifail -1
        !            55:     return $::custom_nfail
        !            56:   }
        !            57: }
        !            58: proc uninstall_custom_faultsim {} {
        !            59:   unset -nocomplain ::FAULTSIM(custom)
        !            60: }
        !            61: 
        !            62: 
        !            63: #-------------------------------------------------------------------------
        !            64: # These tests - indexfault-1.* - Build an index on a smallish table with
        !            65: # all different kinds of fault-injection. The CREATE INDEX is run once
        !            66: # with default options and once with a 50KB soft-heap-limit.
        !            67: #
        !            68: do_execsql_test 1.0 {
        !            69:   BEGIN;
        !            70:     CREATE TABLE t1(x);
        !            71:     INSERT INTO t1 VALUES(randomblob(202));
        !            72:     INSERT INTO t1 SELECT randomblob(202) FROM t1;     --     2
        !            73:     INSERT INTO t1 SELECT randomblob(202) FROM t1;     --     4
        !            74:     INSERT INTO t1 SELECT randomblob(202) FROM t1;     --     8
        !            75:     INSERT INTO t1 SELECT randomblob(202) FROM t1;     --    16
        !            76:     INSERT INTO t1 SELECT randomblob(202) FROM t1;     --    32
        !            77:     INSERT INTO t1 SELECT randomblob(202) FROM t1;     --    64
        !            78:     INSERT INTO t1 SELECT randomblob(202) FROM t1;     --   128
        !            79:     INSERT INTO t1 SELECT randomblob(202) FROM t1;     --   256
        !            80:   COMMIT;
        !            81: }
        !            82: faultsim_save_and_close
        !            83: 
        !            84: do_faultsim_test 1.1 -prep {
        !            85:   faultsim_restore_and_reopen
        !            86: } -body {
        !            87:   execsql { CREATE INDEX i1 ON t1(x) }
        !            88:   faultsim_test_result {0 {}} 
        !            89:   faultsim_integrity_check
        !            90: }
        !            91: ifcapable memorymanage {
        !            92:   set soft_limit [sqlite3_soft_heap_limit 50000]
        !            93:   do_faultsim_test 2.1 -prep {
        !            94:     faultsim_restore_and_reopen
        !            95:   } -body {
        !            96:     execsql { CREATE INDEX i1 ON t1(x) }
        !            97:     faultsim_test_result {0 {}} 
        !            98:   }
        !            99:   sqlite3_soft_heap_limit $soft_limit
        !           100: }
        !           101: 
        !           102: #-------------------------------------------------------------------------
        !           103: # These are similar to the indexfault-1.* tests, except they create an
        !           104: # index with more than one column.
        !           105: #
        !           106: sqlite3 db test.db
        !           107: do_execsql_test 2.0 {
        !           108:   BEGIN;
        !           109:     DROP TABLE IF EXISTS t1;
        !           110:     CREATE TABLE t1(t,u,v,w,x,y,z);
        !           111:     INSERT INTO t1 VALUES(
        !           112:       randomblob(30), randomblob(30), randomblob(30), randomblob(30),
        !           113:       randomblob(30), randomblob(30), randomblob(30)
        !           114:     );
        !           115:     INSERT INTO t1 SELECT 
        !           116:       randomblob(30), randomblob(30), randomblob(30), randomblob(30),
        !           117:       randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 2
        !           118:     INSERT INTO t1 SELECT 
        !           119:       randomblob(30), randomblob(30), randomblob(30), randomblob(30),
        !           120:       randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 4
        !           121:     INSERT INTO t1 SELECT 
        !           122:       randomblob(30), randomblob(30), randomblob(30), randomblob(30),
        !           123:       randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 8
        !           124:     INSERT INTO t1 SELECT 
        !           125:       randomblob(30), randomblob(30), randomblob(30), randomblob(30),
        !           126:       randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 16
        !           127:     INSERT INTO t1 SELECT 
        !           128:       randomblob(30), randomblob(30), randomblob(30), randomblob(30),
        !           129:       randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 32
        !           130:     INSERT INTO t1 SELECT 
        !           131:       randomblob(30), randomblob(30), randomblob(30), randomblob(30),
        !           132:       randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 64
        !           133:     INSERT INTO t1 SELECT 
        !           134:       randomblob(30), randomblob(30), randomblob(30), randomblob(30),
        !           135:       randomblob(30), randomblob(30), randomblob(30) FROM t1;         -- 128
        !           136:   COMMIT;
        !           137: }
        !           138: faultsim_save_and_close
        !           139: 
        !           140: do_faultsim_test 2.1 -prep {
        !           141:   faultsim_restore_and_reopen
        !           142: } -body {
        !           143:   execsql { CREATE INDEX i1 ON t1(t,u,v,w,x,y,z) }
        !           144:   faultsim_test_result {0 {}} 
        !           145:   faultsim_integrity_check
        !           146: }
        !           147: ifcapable memorymanage {
        !           148:   set soft_limit [sqlite3_soft_heap_limit 50000]
        !           149:   do_faultsim_test 2.2 -prep {
        !           150:     faultsim_restore_and_reopen
        !           151:   } -body {
        !           152:     execsql { CREATE INDEX i1 ON t1(t,u,v,w,x,y,z) }
        !           153:     faultsim_test_result {0 {}} 
        !           154:   }
        !           155:   sqlite3_soft_heap_limit $soft_limit
        !           156: }
        !           157: 
        !           158: #-------------------------------------------------------------------------
        !           159: # The following tests - indexfault-2.* - all attempt to build a index
        !           160: # on table t1 in the main database with injected IO errors. Individual
        !           161: # test cases work as follows:
        !           162: #
        !           163: #   3.1: IO errors injected into xOpen() calls.
        !           164: #   3.2: As 7.1, but with a low (50KB) soft-heap-limit.
        !           165: #
        !           166: #   3.3: IO errors injected into the first 200 write() calls made on the
        !           167: #        second temporary file.
        !           168: #   3.4: As 7.3, but with a low (50KB) soft-heap-limit.
        !           169: #
        !           170: #   3.5: After a certain amount of data has been read from the main database
        !           171: #        file (and written into the temporary b-tree), sqlite3_release_memory()
        !           172: #        is called to free as much memory as possible. This causes the temp
        !           173: #        b-tree to be flushed to disk. So that before its contents can be 
        !           174: #        transfered to a PMA they must be read back from disk - creating extra
        !           175: #        opportunities for IO errors.
        !           176: #
        !           177: install_custom_faultsim
        !           178: 
        !           179: # Set up a table to build indexes on. Save the setup using the 
        !           180: # [faultsim_save_and_close] mechanism.
        !           181: # 
        !           182: sqlite3 db test.db
        !           183: do_execsql_test 3.0 {
        !           184:   BEGIN;
        !           185:     DROP TABLE IF EXISTS t1;
        !           186:     CREATE TABLE t1(x);
        !           187:     INSERT INTO t1 VALUES(randomblob(11000));
        !           188:     INSERT INTO t1 SELECT randomblob(11001) FROM t1;     --     2
        !           189:     INSERT INTO t1 SELECT randomblob(11002) FROM t1;     --     4
        !           190:     INSERT INTO t1 SELECT randomblob(11003) FROM t1;     --     8
        !           191:     INSERT INTO t1 SELECT randomblob(11004) FROM t1;     --    16
        !           192:     INSERT INTO t1 SELECT randomblob(11005) FROM t1;     --    32
        !           193:     INSERT INTO t1 SELECT randomblob(11006) FROM t1;     --    64
        !           194:     INSERT INTO t1 SELECT randomblob(11007) FROM t1;     --   128
        !           195:     INSERT INTO t1 SELECT randomblob(11008) FROM t1;     --   256
        !           196:     INSERT INTO t1 SELECT randomblob(11009) FROM t1;     --   512
        !           197:   COMMIT;
        !           198: }
        !           199: faultsim_save_and_close
        !           200: 
        !           201: set ::custom_filter xOpen
        !           202: proc xCustom {args} {
        !           203:   incr ::custom_ifail -1
        !           204:   if {$::custom_ifail==0} {
        !           205:     incr ::custom_nfail
        !           206:     return "SQLITE_IOERR"
        !           207:   }
        !           208:   return "SQLITE_OK"
        !           209: }
        !           210: do_faultsim_test 3.1 -faults custom -prep {
        !           211:   faultsim_restore_and_reopen
        !           212: } -body {
        !           213:   execsql { CREATE INDEX i1 ON t1(x) }
        !           214:   faultsim_test_result {0 {}} 
        !           215: }
        !           216: ifcapable memorymanage {
        !           217:   set soft_limit [sqlite3_soft_heap_limit 50000]
        !           218:   do_faultsim_test 3.2 -faults custom -prep {
        !           219:     faultsim_restore_and_reopen
        !           220:   } -body {
        !           221:     execsql { CREATE INDEX i1 ON t1(x) }
        !           222:     faultsim_test_result {0 {}} 
        !           223:   }
        !           224:   sqlite3_soft_heap_limit $soft_limit
        !           225: }
        !           226: 
        !           227: set ::custom_filter {xOpen xWrite}
        !           228: proc xCustom {method args} {
        !           229:   if {$method == "xOpen"} {
        !           230:     if {[lindex $args 0] == ""} {
        !           231:       incr ::nTmpOpen 1
        !           232:       if {$::nTmpOpen == 3} { return "failme" }
        !           233:     }
        !           234:     return "SQLITE_OK"
        !           235:   }
        !           236:   if {$::custom_ifail<200 && [lindex $args 1] == "failme"} {
        !           237:     incr ::custom_ifail -1
        !           238:     if {$::custom_ifail==0} {
        !           239:       incr ::custom_nfail
        !           240:       return "SQLITE_IOERR"
        !           241:     }
        !           242:   }
        !           243:   return "SQLITE_OK"
        !           244: }
        !           245: 
        !           246: do_faultsim_test 3.3 -faults custom -prep {
        !           247:   faultsim_restore_and_reopen
        !           248:   set ::nTmpOpen 0
        !           249: } -body {
        !           250:   execsql { CREATE INDEX i1 ON t1(x) }
        !           251:   faultsim_test_result {0 {}} 
        !           252: }
        !           253: 
        !           254: ifcapable memorymanage {
        !           255:   set soft_limit [sqlite3_soft_heap_limit 50000]
        !           256:   do_faultsim_test 3.4 -faults custom -prep {
        !           257:     faultsim_restore_and_reopen
        !           258:     set ::nTmpOpen 0
        !           259:   } -body {
        !           260:     execsql { CREATE INDEX i1 ON t1(x) }
        !           261:     faultsim_test_result {0 {}} 
        !           262:   }
        !           263:   sqlite3_soft_heap_limit $soft_limit
        !           264: }
        !           265: 
        !           266: uninstall_custom_faultsim
        !           267: 
        !           268: #-------------------------------------------------------------------------
        !           269: # Test 4: After a certain amount of data has been read from the main database
        !           270: # file (and written into the temporary b-tree), sqlite3_release_memory() is
        !           271: # called to free as much memory as possible. This causes the temp b-tree to be
        !           272: # flushed to disk. So that before its contents can be transfered to a PMA they
        !           273: # must be read back from disk - creating extra opportunities for IO errors.
        !           274: # 
        !           275: install_custom_faultsim
        !           276: 
        !           277: catch { db close }
        !           278: forcedelete test.db
        !           279: sqlite3 db test.db
        !           280: 
        !           281: do_execsql_test 4.0 {
        !           282:   BEGIN;
        !           283:     DROP TABLE IF EXISTS t1;
        !           284:     CREATE TABLE t1(x);
        !           285:     INSERT INTO t1 VALUES(randomblob(11000));
        !           286:     INSERT INTO t1 SELECT randomblob(11001) FROM t1;     --     2
        !           287:     INSERT INTO t1 SELECT randomblob(11002) FROM t1;     --     4
        !           288:     INSERT INTO t1 SELECT randomblob(11003) FROM t1;     --     8
        !           289:     INSERT INTO t1 SELECT randomblob(11004) FROM t1;     --    16
        !           290:     INSERT INTO t1 SELECT randomblob(11005) FROM t1;     --    32
        !           291:     INSERT INTO t1 SELECT randomblob(11005) FROM t1;     --    64
        !           292:   COMMIT;
        !           293: }
        !           294: faultsim_save_and_close
        !           295: 
        !           296: testvfs tvfs 
        !           297: tvfs script xRead
        !           298: tvfs filter xRead
        !           299: set ::nRead 0
        !           300: proc xRead {method file args} {
        !           301:   if {[file tail $file] == "test.db"} { incr ::nRead }
        !           302: }
        !           303: 
        !           304: do_test 4.1 {
        !           305:   sqlite3 db test.db -vfs tvfs
        !           306:   execsql { CREATE INDEX i1 ON t1(x) }
        !           307: } {}
        !           308: 
        !           309: db close
        !           310: tvfs delete
        !           311: 
        !           312: set ::custom_filter xRead
        !           313: proc xCustom {method file args} {
        !           314:   incr ::nReadCall
        !           315:   if {$::nReadCall >= ($::nRead/5)} {
        !           316:     if {$::nReadCall == ($::nRead/5)} {
        !           317:       set nByte [sqlite3_release_memory [expr 64*1024*1024]]
        !           318:       sqlite3_soft_heap_limit 20000
        !           319:     }
        !           320:     if {$file == ""} {
        !           321:       incr ::custom_ifail -1
        !           322:       if {$::custom_ifail==0} {
        !           323:         incr ::custom_nfail
        !           324:         return "SQLITE_IOERR"
        !           325:       }
        !           326:     }
        !           327:   }
        !           328:   return "SQLITE_OK"
        !           329: }
        !           330: 
        !           331: do_faultsim_test 4.2 -faults custom -prep {
        !           332:   faultsim_restore_and_reopen
        !           333:   set ::nReadCall 0
        !           334:   sqlite3_soft_heap_limit 0
        !           335: } -body {
        !           336:   execsql { CREATE INDEX i1 ON t1(x) }
        !           337:   faultsim_test_result {0 {}} 
        !           338: }
        !           339: 
        !           340: uninstall_custom_faultsim
        !           341: 
        !           342: finish_test

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