1# 2005 December 30 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# The focus of the tests in this file are IO errors that occur in a shared 13# cache context. What happens to connection B if one connection A encounters 14# an IO-error whilst reading or writing the file-system? 15# 16# $Id: shared_err.test,v 1.9 2006/01/24 16:37:59 danielk1977 Exp $ 17 18proc skip {args} {} 19 20 21set testdir [file dirname $argv0] 22source $testdir/tester.tcl 23db close 24 25ifcapable !shared_cache||!subquery { 26 finish_test 27 return 28} 29set ::enable_shared_cache [sqlite3_enable_shared_cache 1] 30 31 32# Todo: This is a copy of the [do_malloc_test] proc in malloc.test 33# It would be better if these were consolidated. 34 35# Usage: do_malloc_test <test number> <options...> 36# 37# The first argument, <test number>, is an integer used to name the 38# tests executed by this proc. Options are as follows: 39# 40# -tclprep TCL script to run to prepare test. 41# -sqlprep SQL script to run to prepare test. 42# -tclbody TCL script to run with malloc failure simulation. 43# -sqlbody TCL script to run with malloc failure simulation. 44# -cleanup TCL script to run after the test. 45# 46# This command runs a series of tests to verify SQLite's ability 47# to handle an out-of-memory condition gracefully. It is assumed 48# that if this condition occurs a malloc() call will return a 49# NULL pointer. Linux, for example, doesn't do that by default. See 50# the "BUGS" section of malloc(3). 51# 52# Each iteration of a loop, the TCL commands in any argument passed 53# to the -tclbody switch, followed by the SQL commands in any argument 54# passed to the -sqlbody switch are executed. Each iteration the 55# Nth call to sqliteMalloc() is made to fail, where N is increased 56# each time the loop runs starting from 1. When all commands execute 57# successfully, the loop ends. 58# 59proc do_malloc_test {tn args} { 60 array unset ::mallocopts 61 array set ::mallocopts $args 62 63 set ::go 1 64 for {set ::n 1} {$::go && $::n < 50000} {incr ::n} { 65 do_test shared_malloc-$tn.$::n { 66 67 # Remove all traces of database files test.db and test2.db from the files 68 # system. Then open (empty database) "test.db" with the handle [db]. 69 # 70 sqlite_malloc_fail 0 71 catch {db close} 72 catch {file delete -force test.db} 73 catch {file delete -force test.db-journal} 74 catch {file delete -force test2.db} 75 catch {file delete -force test2.db-journal} 76 catch {sqlite3 db test.db} 77 set ::DB [sqlite3_connection_pointer db] 78 79 # Execute any -tclprep and -sqlprep scripts. 80 # 81 if {[info exists ::mallocopts(-tclprep)]} { 82 eval $::mallocopts(-tclprep) 83 } 84 if {[info exists ::mallocopts(-sqlprep)]} { 85 execsql $::mallocopts(-sqlprep) 86 } 87 88 # Now set the ${::n}th malloc() to fail and execute the -tclbody and 89 # -sqlbody scripts. 90 # 91 sqlite_malloc_fail $::n 92 set ::mallocbody {} 93 if {[info exists ::mallocopts(-tclbody)]} { 94 append ::mallocbody "$::mallocopts(-tclbody)\n" 95 } 96 if {[info exists ::mallocopts(-sqlbody)]} { 97 append ::mallocbody "db eval {$::mallocopts(-sqlbody)}" 98 } 99 set v [catch $::mallocbody msg] 100 101 set leftover [lindex [sqlite_malloc_stat] 2] 102 if {$leftover>0} { 103 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 104 set ::go 0 105 if {$v} { 106 puts "\nError message returned: $msg" 107 } else { 108 set v {1 1} 109 } 110 } else { 111 set v2 [expr {$msg=="" || $msg=="out of memory"}] 112 if {!$v2} {puts "\nError message returned: $msg"} 113 lappend v $v2 114 } 115 } {1 1} 116 117 sqlite_malloc_fail 0 118 if {[info exists ::mallocopts(-cleanup)]} { 119 catch [list uplevel #0 $::mallocopts(-cleanup)] msg 120 } 121 } 122 unset ::mallocopts 123} 124 125 126do_ioerr_test shared_ioerr-1 -tclprep { 127 sqlite3 db2 test.db 128 execsql { 129 PRAGMA read_uncommitted = 1; 130 CREATE TABLE t1(a,b,c); 131 BEGIN; 132 SELECT * FROM sqlite_master; 133 } db2 134} -sqlbody { 135 SELECT * FROM sqlite_master; 136 INSERT INTO t1 VALUES(1,2,3); 137 BEGIN TRANSACTION; 138 INSERT INTO t1 VALUES(1,2,3); 139 INSERT INTO t1 VALUES(4,5,6); 140 ROLLBACK; 141 SELECT * FROM t1; 142 BEGIN TRANSACTION; 143 INSERT INTO t1 VALUES(1,2,3); 144 INSERT INTO t1 VALUES(4,5,6); 145 COMMIT; 146 SELECT * FROM t1; 147 DELETE FROM t1 WHERE a<100; 148} -cleanup { 149 do_test shared_ioerr-1.$n.cleanup.1 { 150 set res [catchsql { 151 SELECT * FROM t1; 152 } db2] 153 set possible_results [list \ 154 "1 {disk I/O error}" \ 155 "0 {1 2 3}" \ 156 "0 {1 2 3 1 2 3 4 5 6}" \ 157 "0 {1 2 3 1 2 3 4 5 6 1 2 3 4 5 6}" \ 158 "0 {}" \ 159 ] 160 set rc [expr [lsearch -exact $possible_results $res] >= 0] 161 if {$rc != 1} { 162 puts "" 163 puts "Result: $res" 164 } 165 set rc 166 } {1} 167 db2 close 168} 169 170do_ioerr_test shared_ioerr-2 -tclprep { 171 sqlite3 db2 test.db 172 execsql { 173 PRAGMA read_uncommitted = 1; 174 BEGIN; 175 CREATE TABLE t1(a, b); 176 INSERT INTO t1(oid) VALUES(NULL); 177 INSERT INTO t1(oid) SELECT NULL FROM t1; 178 INSERT INTO t1(oid) SELECT NULL FROM t1; 179 INSERT INTO t1(oid) SELECT NULL FROM t1; 180 INSERT INTO t1(oid) SELECT NULL FROM t1; 181 INSERT INTO t1(oid) SELECT NULL FROM t1; 182 INSERT INTO t1(oid) SELECT NULL FROM t1; 183 INSERT INTO t1(oid) SELECT NULL FROM t1; 184 INSERT INTO t1(oid) SELECT NULL FROM t1; 185 INSERT INTO t1(oid) SELECT NULL FROM t1; 186 INSERT INTO t1(oid) SELECT NULL FROM t1; 187 UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789'; 188 CREATE INDEX i1 ON t1(a); 189 COMMIT; 190 BEGIN; 191 SELECT * FROM sqlite_master; 192 } db2 193} -tclbody { 194 set ::residx 0 195 execsql {DELETE FROM t1 WHERE 0 = (a % 2);} 196 incr ::residx 197 198 # When this transaction begins the table contains 512 entries. The 199 # two statements together add 512+146 more if it succeeds. 200 # (1024/7==146) 201 execsql {BEGIN;} 202 execsql {INSERT INTO t1 SELECT a+1, b FROM t1;} 203 execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);} 204 execsql {COMMIT;} 205 206 incr ::residx 207} -cleanup { 208 do_test shared_ioerr-2.$n.cleanup.1 { 209 set res [catchsql { 210 SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a); 211 } db2] 212 set possible_results [list \ 213 {0 {1024 1 1024}} \ 214 {0 {1023 1 512}} \ 215 {0 {string994 1 1170}} \ 216 ] 217 set idx [lsearch -exact $possible_results $res] 218 set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}] 219 if {!$success} { 220 puts "" 221 puts "Result: \"$res\" ($::residx)" 222 } 223 set success 224 } {1} 225 db2 close 226} 227 228# This test is designed to provoke an IO error when a cursor position is 229# "saved" (because another cursor is going to modify the underlying table). 230# 231do_ioerr_test shared_ioerr-3 -tclprep { 232 sqlite3 db2 test.db 233 execsql { 234 PRAGMA read_uncommitted = 1; 235 PRAGMA cache_size = 10; 236 BEGIN; 237 CREATE TABLE t1(a, b, UNIQUE(a, b)); 238 } db2 239 for {set i 0} {$i < 200} {incr i} { 240 set a [string range [string repeat "[format %03d $i]." 5] 0 end-1] 241 242 set b [string repeat $i 2000] 243 execsql {INSERT INTO t1 VALUES($a, $b)} db2 244 } 245 execsql {COMMIT} db2 246 set ::DB2 [sqlite3_connection_pointer db2] 247 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] 248 sqlite3_step $::STMT ;# Cursor points at 000.000.000.000 249 sqlite3_step $::STMT ;# Cursor points at 001.001.001.001 250 251} -tclbody { 252 execsql { 253 BEGIN; 254 INSERT INTO t1 VALUES('201.201.201.201.201', NULL); 255 UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%'; 256 COMMIT; 257 } 258} -cleanup { 259 do_test shared_ioerr-3.$n.cleanup.1 { 260 sqlite3_step $::STMT 261 } {SQLITE_ROW} 262 do_test shared_ioerr-3.$n.cleanup.2 { 263 sqlite3_column_text $::STMT 0 264 } {002.002.002.002.002} 265 do_test shared_ioerr-3.$n.cleanup.3 { 266 sqlite3_finalize $::STMT 267 } {SQLITE_OK} 268# db2 eval {select * from sqlite_master} 269 db2 close 270} 271 272# Only run these tests if memory debugging is turned on. 273# 274if {[info command sqlite_malloc_stat]==""} { 275 puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." 276 db close 277 sqlite3_enable_shared_cache $::enable_shared_cache 278 finish_test 279 return 280} 281 282# Provoke a malloc() failure when a cursor position is being saved. This 283# only happens with index cursors (because they malloc() space to save the 284# current key value). It does not happen with tables, because an integer 285# key does not require a malloc() to store. 286# 287# The library should return an SQLITE_NOMEM to the caller. The query that 288# owns the cursor (the one for which the position is not saved) should 289# continue unaffected. 290# 291do_malloc_test 4 -tclprep { 292 sqlite3 db2 test.db 293 execsql { 294 PRAGMA read_uncommitted = 1; 295 BEGIN; 296 CREATE TABLE t1(a, b, UNIQUE(a, b)); 297 } db2 298 for {set i 0} {$i < 5} {incr i} { 299 set a [string repeat $i 10] 300 set b [string repeat $i 2000] 301 execsql {INSERT INTO t1 VALUES($a, $b)} db2 302 } 303 execsql {COMMIT} db2 304 set ::DB2 [sqlite3_connection_pointer db2] 305 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] 306 sqlite3_step $::STMT ;# Cursor points at 0000000000 307 sqlite3_step $::STMT ;# Cursor points at 1111111111 308} -tclbody { 309 execsql { 310 INSERT INTO t1 VALUES(6, NULL); 311 } 312} -cleanup { 313 do_test shared_malloc-4.$::n.cleanup.1 { 314 set ::rc [sqlite3_step $::STMT] 315 expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ABORT"} 316 } {1} 317 if {$::rc=="SQLITE_ROW"} { 318 do_test shared_malloc-4.$::n.cleanup.2 { 319 sqlite3_column_text $::STMT 0 320 } {2222222222} 321 } 322 do_test shared_malloc-4.$::n.cleanup.3 { 323 sqlite3_finalize $::STMT 324 } {SQLITE_OK} 325# db2 eval {select * from sqlite_master} 326 db2 close 327} 328 329do_malloc_test 5 -tclbody { 330 sqlite3 dbX test.db 331 sqlite3 dbY test.db 332 dbX close 333 dbY close 334} -cleanup { 335 catch {dbX close} 336 catch {dbY close} 337} 338 339do_malloc_test 6 -tclbody { 340 catch {db close} 341 sqlite3_thread_cleanup 342 sqlite3_enable_shared_cache 0 343} -cleanup { 344 sqlite3_enable_shared_cache 1 345} 346 347do_test shared_misuse-7.1 { 348 sqlite3 db test.db 349 catch { 350 sqlite3_enable_shared_cache 0 351 } msg 352 set msg 353} {library routine called out of sequence} 354 355# Again provoke a malloc() failure when a cursor position is being saved, 356# this time during a ROLLBACK operation by some other handle. 357# 358# The library should return an SQLITE_NOMEM to the caller. The query that 359# owns the cursor (the one for which the position is not saved) should 360# be aborted. 361# 362set ::aborted 0 363do_malloc_test 8 -tclprep { 364 sqlite3 db2 test.db 365 execsql { 366 PRAGMA read_uncommitted = 1; 367 BEGIN; 368 CREATE TABLE t1(a, b, UNIQUE(a, b)); 369 } db2 370 for {set i 0} {$i < 2} {incr i} { 371 set a [string repeat $i 10] 372 set b [string repeat $i 2000] 373 execsql {INSERT INTO t1 VALUES($a, $b)} db2 374 } 375 execsql {COMMIT} db2 376 set ::DB2 [sqlite3_connection_pointer db2] 377 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] 378 sqlite3_step $::STMT ;# Cursor points at 0000000000 379 sqlite3_step $::STMT ;# Cursor points at 1111111111 380} -tclbody { 381 execsql { 382 BEGIN; 383 INSERT INTO t1 VALUES(6, NULL); 384 ROLLBACK; 385 } 386} -cleanup { 387 do_test shared_malloc-8.$::n.cleanup.1 { 388 lrange [execsql { 389 SELECT a FROM t1; 390 } db2] 0 1 391 } {0000000000 1111111111} 392 do_test shared_malloc-8.$::n.cleanup.2 { 393 set rc1 [sqlite3_step $::STMT] 394 set rc2 [sqlite3_finalize $::STMT] 395 if {$rc1=="SQLITE_ABORT"} { 396 incr ::aborted 397 } 398 expr { 399 ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") || 400 ($rc1=="SQLITE_ABORT" && $rc2=="SQLITE_OK") 401 } 402 } {1} 403 db2 close 404} 405do_test shared_malloc-8.X { 406 # Test that one or more queries were aborted due to the malloc() failure. 407 expr $::aborted>=1 408} {1} 409 410catch {db close} 411sqlite3_enable_shared_cache $::enable_shared_cache 412finish_test 413