| OLD | NEW |
| (Empty) |
| 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 | |
| OLD | NEW |