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>