diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/malloc_common.tcl | 142 | ||||
-rw-r--r-- | test/wal2.test | 21 | ||||
-rw-r--r-- | test/walfault.test | 312 |
3 files changed, 268 insertions, 207 deletions
diff --git a/test/malloc_common.tcl b/test/malloc_common.tcl index 057cf7c41..902f68310 100644 --- a/test/malloc_common.tcl +++ b/test/malloc_common.tcl @@ -23,6 +23,50 @@ ifcapable builtin_test { return 0 } +# Transient and persistent OOM errors: +# +set FAULTSIM(oom-transient) [list \ + -injectstart {oom_injectstart 0} \ + -injectstop oom_injectstop \ + -injecterrlist {{1 {out of memory}}} \ +] +set FAULTSIM(oom-persistent) [list \ + -injectstart {oom_injectstart 1000000} \ + -injectstop oom_injectstop \ + -injecterrlist {{1 {out of memory}}} \ +] + +# Transient and persistent IO errors: +# +set FAULTSIM(ioerr-transient) [list \ + -injectstart {ioerr_injectstart 0} \ + -injectstop ioerr_injectstop \ + -injecterrlist {{1 {disk I/O error}}} \ +] +set FAULTSIM(ioerr-persistent) [list \ + -injectstart {ioerr_injectstart 1} \ + -injectstop ioerr_injectstop \ + -injecterrlist {{1 {disk I/O error}}} \ +] + +# Transient and persistent SHM errors: +# +set FAULTSIM(shmerr-transient) [list \ + -injectinstall shmerr_injectinstall \ + -injectstart {shmerr_injectstart 0} \ + -injectstop shmerr_injectstop \ + -injecterrlist {{1 {disk I/O error}}} \ + -injectuninstall shmerr_injectuninstall \ +] +set FAULTSIM(shmerr-persistent) [list \ + -injectinstall shmerr_injectinstall \ + -injectstart {shmerr_injectstart 1} \ + -injectstop shmerr_injectstop \ + -injecterrlist {{1 {disk I/O error}}} \ + -injectuninstall shmerr_injectuninstall \ +] + + #-------------------------------------------------------------------------- # Usage do_faultsim_test NAME ?OPTIONS...? @@ -36,10 +80,9 @@ ifcapable builtin_test { # -test Script to execute after -body. # proc do_faultsim_test {name args} { - set DEFAULT(-faults) [list \ - oom-transient oom-persistent \ - ioerr-transient ioerr-persistent \ - ] + global FAULTSIM + + set DEFAULT(-faults) [array names FAULTSIM] set DEFAULT(-prep) "" set DEFAULT(-body) "" set DEFAULT(-test) "" @@ -50,35 +93,16 @@ proc do_faultsim_test {name args} { if {[info exists DEFAULT($o)]==0} { error "unknown option: $o" } } - set A(oom-transient) [list \ - -injectstart {oom_injectstart 0} \ - -injectstop oom_injectstop \ - -injecterrlist {{1 {out of memory}}} \ - ] - set A(oom-persistent) [list \ - -injectstart {oom_injectstart 1000000} \ - -injectstop oom_injectstop \ - -injecterrlist {{1 {out of memory}}} \ - ] - - set A(ioerr-transient) [list \ - -injectstart {ioerr_injectstart 0} \ - -injectstop ioerr_injectstop \ - -injecterrlist {{1 {disk I/O error}}} \ - ] - - set A(ioerr-persistent) [list \ - -injectstart {ioerr_injectstart 1} \ - -injectstop ioerr_injectstop \ - -injecterrlist {{1 {disk I/O error}}} \ - ] - + set faultlist [list] foreach f $O(-faults) { - if {[info exists A($f)]==0} { error "unknown fault: $f" } + set flist [array names FAULTSIM $f] + if {[llength $flist]==0} { error "unknown fault: $f" } + set faultlist [concat $faultlist $flist] } + set testspec [list -prep $O(-prep) -body $O(-body) -test $O(-test)] - foreach f $O(-faults) { - eval do_one_faultsim_test "$name-$f" $A($f) $testspec + foreach f [lsort -unique $faultlist] { + eval do_one_faultsim_test "$name-$f" $FAULTSIM($f) $testspec } } @@ -121,9 +145,20 @@ proc faultsim_restore_and_reopen {} { sqlite3_db_config_lookaside db 0 0 0 } +proc faultsim_integrity_check {{db db}} { + set ic [$db eval { PRAGMA integrity_check }] + if {$ic != "ok"} { error "Integrity check: $ic" } +} + +proc faultsim_delete_and_reopen {{file test.db}} { + catch { db close } + file delete -force test.db test.db-wal test.db-journal + sqlite3 db test.db +} + -# The following procs are used as [do_faultsim_test] when injecting OOM -# faults into test cases. +# The following procs are used as [do_one_faultsim_test] callbacks when +# injecting OOM faults into test cases. # proc oom_injectstart {nRepeat iFail} { sqlite3_memdebug_fail $iFail -repeat $nRepeat @@ -132,6 +167,9 @@ proc oom_injectstop {} { sqlite3_memdebug_fail -1 } +# The following procs are used as [do_one_faultsim_test] callbacks when +# injecting IO error faults into test cases. +# proc ioerr_injectstart {persist iFail} { set ::sqlite_io_error_persist $persist set ::sqlite_io_error_pending $iFail @@ -146,6 +184,24 @@ proc ioerr_injectstop {} { return $sv } +# The following procs are used as [do_one_faultsim_test] callbacks when +# injecting shared-memory related error faults into test cases. +# +proc shmerr_injectinstall {} { + testvfs shmfault -default true +} +proc shmerr_injectuninstall {} { + catch {db close} + catch {db2 close} + shmfault delete +} +proc shmerr_injectstart {persist iFail} { + shmfault ioerr $iFail $persist +} +proc shmerr_injectstop {} { + shmfault ioerr 0 0 +} + # This command is not called directly. It is used by the # [faultsim_test_result] command created by [do_faultsim_test] and used # by -test scripts. @@ -173,6 +229,10 @@ proc faultsim_test_result_int {args} { # -injecterrlist List of generally acceptable test results (i.e. error # messages). Example: [list {1 {out of memory}}] # +# -injectinstall +# +# -injectuninstall +# # -prep Script to execute before -body. # # -body Script to execute (with fault injection). @@ -181,12 +241,14 @@ proc faultsim_test_result_int {args} { # proc do_one_faultsim_test {testname args} { - set DEFAULT(-injectstart) {oom_injectstart 0} - set DEFAULT(-injectstop) {oom_injectstop} - set DEFAULT(-injecterrlist) [list {1 {out of memory}}] - set DEFAULT(-prep) "" - set DEFAULT(-body) "" - set DEFAULT(-test) "" + set DEFAULT(-injectstart) "expr" + set DEFAULT(-injectstop) "expr 0" + set DEFAULT(-injecterrlist) [list] + set DEFAULT(-injectinstall) "" + set DEFAULT(-injectuninstall) "" + set DEFAULT(-prep) "" + set DEFAULT(-body) "" + set DEFAULT(-test) "" array set O [array get DEFAULT] array set O $args @@ -199,6 +261,8 @@ proc do_one_faultsim_test {testname args} { uplevel faultsim_test_result_int \$args [list $O(-injecterrlist)] " + eval $O(-injectinstall) + set stop 0 for {set iFail 1} {!$stop} {incr iFail} { @@ -228,6 +292,8 @@ proc do_one_faultsim_test {testname args} { # if {$nfail==0} { set stop 1 } } + + eval $O(-injectuninstall) } # Usage: do_malloc_test <test number> <options...> diff --git a/test/wal2.test b/test/wal2.test index 91ae546ee..d8e556080 100644 --- a/test/wal2.test +++ b/test/wal2.test @@ -72,7 +72,8 @@ proc incr_tvfs_hdr {file idx incrval} { # do_test wal2-1.0 { proc tvfs_cb {method args} { return SQLITE_OK } - testvfs tvfs tvfs_cb + testvfs tvfs + tvfs script tvfs_cb sqlite3 db test.db -vfs tvfs sqlite3 db2 test.db -vfs tvfs @@ -166,7 +167,8 @@ set LOCKS [list \ ] do_test wal2-2.0 { - testvfs tvfs tvfs_cb + testvfs tvfs + tvfs script tvfs_cb proc tvfs_cb {method args} { if {$method == "xShmOpen"} { set ::shm_file [lindex $args 0] } return SQLITE_OK @@ -281,7 +283,8 @@ do_test wal2-3.0 { return 0 } - testvfs tvfs tvfs_cb + testvfs tvfs + tvfs script tvfs_cb sqlite3 db test.db -vfs tvfs db busy busyhandler @@ -348,15 +351,13 @@ do_test wal2-4.1 { } {wal} do_test wal2-4.2 { db close - proc ok {args} {return SQLITE_OK} - testvfs -noshm tvfs ok + testvfs tvfs -noshm 1 sqlite3 db test.db -vfs tvfs catchsql { SELECT * FROM data } } {1 {unable to open database file}} do_test wal2-4.3 { db close - proc ok {args} {return SQLITE_OK} - testvfs tvfs ok + testvfs tvfs sqlite3 db test.db -vfs tvfs catchsql { SELECT * FROM data } } {0 {{need xShmOpen to see this}}} @@ -388,7 +389,8 @@ do_test wal2-5.1 { } set tvfs_cb_return SQLITE_OK - testvfs tvfs tvfs_cb + testvfs tvfs + tvfs script tvfs_cb sqlite3 db test.db -vfs tvfs execsql { @@ -578,7 +580,8 @@ do_test wal2-6.4.1 { if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] } return "SQLITE_OK" } - testvfs tvfs tvfs_cb + testvfs tvfs + tvfs script tvfs_cb sqlite3 db test.db -vfs tvfs } {} diff --git a/test/walfault.test b/test/walfault.test index 499f794bb..edb78358e 100644 --- a/test/walfault.test +++ b/test/walfault.test @@ -91,13 +91,8 @@ do_faultsim_test walfault-2 -prep { } -body { execsql { SELECT count(*) FROM x } } -test { - faultsim_test_result {0 8} - - # Run the integrity_check to make sure nothing strange has occurred. - # - set ic [db eval { PRAGMA integrity_check }] - if {$ic != "ok"} { error "Integrity check: $ic" } + faultsim_integrity_check } #-------------------------------------------------------------------------- @@ -126,116 +121,70 @@ do_faultsim_test walfault-3 -prep { faultsim_test_result {0 {}} } -# A [testvfs] callback for the VFS created by [do_shmfault_test]. This -# callback injects SQLITE_IOERR faults into methods for which an entry -# in array ::shmfault_ioerr_methods is defined. For example, to enable -# errors in xShmOpen: -# -# set ::shmfault_ioerr_methods(xShmOpen) 1 -# -# Faults are not injected into xShmRelease, xShmClose or xShmLock method -# calls. The global tcl variables used are: -# -# $::shmfault_ioerr_countdown -# $::shmfault_ioerr_persist -# -proc shmfault_vfs_cb {method args} { - - # If ::shmfault_ioerr_countdown is not set, always return SQLITE_OK. - # - if {[info exists ::shmfault_ioerr_countdown]==0} { return SQLITE_OK } - - incr ::shmfault_ioerr_countdown -1 - if { ($::shmfault_ioerr_countdown==0) - || ($::shmfault_ioerr_countdown<=0 && $::shmfault_ioerr_persist) - } { - return SQLITE_IOERR +file delete -force test.db test.db-wal test.db-journal +faultsim_save_and_close +do_faultsim_test walfault-4 -prep { + faultsim_restore_and_reopen +} -body { + execsql { + PRAGMA journal_mode = WAL; + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('a', 'b'); + PRAGMA wal_checkpoint; + SELECT * FROM t1; } - return SQLITE_OK -} - -# Options are: -# -# -tclprep TCL -# -sqlprep SQL -# -sqlbody SQL -# -proc do_shmfault_test {name args} { - - set A(-tclprep) "sqlite3 db test.db -vfs shmfault" - set A(-sqlprep) "" - set A(-sqlbody) "" - set A(-methods) [list xShmGet xShmOpen xShmSize] - set A(-coverageonly) 0 - array set A $args - - # Create a VFS to use: - testvfs shmfault shmfault_vfs_cb - shmfault filter $A(-methods) - - foreach mode {transient persistent} { - set ::shmfault_ioerr_persist [expr {$mode == "persistent"}] - - for {set nDelay 1} {$nDelay < 10000} {incr nDelay} { - - file delete -force test.db test.db-wal test.db-journal - - eval $A(-tclprep) - db eval $A(-sqlprep) - - set ::shmfault_ioerr_countdown $nDelay - set rc [catch { db eval $A(-sqlbody) } msg] - set hit_error [expr {$::shmfault_ioerr_countdown<=0}] - unset ::shmfault_ioerr_countdown +} -test { + faultsim_test_result {0 {wal a b}} + faultsim_integrity_check +} - catch { db close } - - if {$A(-coverageonly)} { set rc $hit_error } - do_test $name-$mode.$nDelay.1 [list set {} $hit_error] $rc - - if {$hit_error==0} break - } +do_test walfault-5-pre-1 { + catch { db close } + file delete -force test.db test.db-wal test.db-journal + sqlite3 db test.db + execsql { + PRAGMA page_size = 512; + PRAGMA journal_mode = WAL; } - - shmfault delete -} - -do_shmfault_test walfault-shm-1 -sqlbody { - PRAGMA journal_mode = WAL; - CREATE TABLE t1(a PRIMARY KEY, b); - INSERT INTO t1 VALUES('a', 'b'); - PRAGMA wal_checkpoint; + faultsim_save_and_close +} {} +do_faultsim_test walfault-5 -faults shmerr* -prep { + faultsim_restore_and_reopen + execsql { PRAGMA wal_autocheckpoint = 0 } + shmfault filter xShmSize +} -body { + execsql { + CREATE TABLE t1(x); + BEGIN; + INSERT INTO t1 VALUES(randomblob(400)); /* 1 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 32 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 64 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 128 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 256 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 512 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 1024 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2048 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4096 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8192 */ + INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16384 */ + COMMIT; + SELECT count(*) FROM t1; + } +} -test { + faultsim_test_result {0 16384} + faultsim_integrity_check } -do_shmfault_test walfault-shm-2 -methods xShmSize -sqlprep { - PRAGMA page_size = 512; - PRAGMA journal_mode = WAL; - PRAGMA wal_autocheckpoint = 0; -} -sqlbody { - CREATE TABLE t1(x); - BEGIN; - INSERT INTO t1 VALUES(randomblob(400)); /* 1 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 32 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 64 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 128 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 256 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 512 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 1024 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2048 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4096 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8192 */ - INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16384 */ - COMMIT; -} -do_shmfault_test walfault-shm-3 -methods xShmSize -tclprep { - sqlite3 db test.db -vfs shmfault - shmfault filter {} - db eval { +do_test walfault-6-pre-1 { + catch { db close } + file delete -force test.db test.db-wal test.db-journal + sqlite3 db test.db + execsql { PRAGMA page_size = 512; PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0; @@ -258,22 +207,23 @@ do_shmfault_test walfault-shm-3 -methods xShmSize -tclprep { INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16384 */ COMMIT; } - - set ::shmfault_ioerr_countdown 1 - shmfault filter xShmGet - db close - shmfault filter {} - if {[file exists test.db-wal]==0} {error "Failed to create WAL file!"} - - sqlite3 db test.db -vfs shmfault -} -sqlbody { - SELECT count(*) FROM t1; + faultsim_save_and_close +} {} +do_faultsim_test walfault-6 -faults shmerr* -prep { + faultsim_restore_and_reopen + shmfault filter xShmSize +} -body { + execsql { SELECT count(*) FROM t1 } +} -test { + faultsim_test_result {0 16384} + faultsim_integrity_check + set n [db one {SELECT count(*) FROM t1}] + if {$n != 16384 && $n != 0} { error "Incorrect number of rows: $n" } } -do_shmfault_test walfault-shm-4 -tclprep { - sqlite3 db test.db -vfs shmfault - unset -nocomplain ::shmfault_ioerr_countdown - db eval { +do_test walfault-7-pre-1 { + faultsim_delete_and_reopen + execsql { PRAGMA page_size = 512; PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0; @@ -284,45 +234,86 @@ do_shmfault_test walfault-shm-4 -tclprep { INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4 */ COMMIT; } - - set ::shmfault_ioerr_countdown 1 - shmfault filter xShmGet - db close - shmfault filter {} - if {[file exists test.db-wal]==0} {error "Failed to create WAL file!"} - sqlite3 db test.db -vfs shmfault -} -sqlbody { - SELECT count(*) FROM t1; + faultsim_save_and_close +} {} +do_faultsim_test walfault-7 -prep { + faultsim_restore_and_reopen +} -body { + execsql { SELECT count(*) FROM t1 } +} -test { + faultsim_test_result {0 4} + set n [db one {SELECT count(*) FROM t1}] + if {$n != 4 && $n != 0} { error "Incorrect number of rows: $n" } } -do_shmfault_test walfault-shm-5.1 -coverageonly 1 -sqlprep { - PRAGMA cache_size = 10; - PRAGMA journal_mode = WAL; - CREATE TABLE abc(a PRIMARY KEY); - INSERT INTO abc VALUES(randomblob(900)); -} -sqlbody { - BEGIN; - INSERT INTO abc SELECT randomblob(900) FROM abc; /* 1 */ - INSERT INTO abc SELECT randomblob(900) FROM abc; /* 2 */ - INSERT INTO abc SELECT randomblob(900) FROM abc; /* 4 */ - INSERT INTO abc SELECT randomblob(900) FROM abc; /* 8 */ - ROLLBACK; +do_test walfault-8-pre-1 { + faultsim_delete_and_reopen + execsql { + PRAGMA journal_mode = WAL; + CREATE TABLE abc(a PRIMARY KEY); + INSERT INTO abc VALUES(randomblob(900)); + } + faultsim_save_and_close +} {} +do_faultsim_test walfault-8 -prep { + faultsim_restore_and_reopen + execsql { PRAGMA cache_size = 10 } +} -body { + execsql { + BEGIN; + INSERT INTO abc SELECT randomblob(900) FROM abc; /* 1 */ + --INSERT INTO abc SELECT randomblob(900) FROM abc; /* 2 */ + --INSERT INTO abc SELECT randomblob(900) FROM abc; /* 4 */ + --INSERT INTO abc SELECT randomblob(900) FROM abc; /* 8 */ + ROLLBACK; + SELECT count(*) FROM abc; + } +} -test { + faultsim_test_result {0 1} + + faultsim_integrity_check + catch { db eval ROLLBACK } + faultsim_integrity_check + + set n [db one {SELECT count(*) FROM abc}] + if {$n != 1} { error "Incorrect number of rows: $n" } } -do_shmfault_test walfault-shm-5.2 -coverageonly 1 -sqlprep { - PRAGMA cache_size = 10; - PRAGMA journal_mode = WAL; - CREATE TABLE abc(a PRIMARY KEY); - INSERT INTO abc VALUES(randomblob(900)); -} -sqlbody { - BEGIN; - INSERT INTO abc SELECT randomblob(900) FROM abc; /* 1 */ - SAVEPOINT spoint; - INSERT INTO abc SELECT randomblob(900) FROM abc; /* 2 */ - INSERT INTO abc SELECT randomblob(900) FROM abc; /* 4 */ - INSERT INTO abc SELECT randomblob(900) FROM abc; /* 8 */ - ROLLBACK TO spoint; - COMMIT; +do_test walfault-9-pre-1 { + faultsim_delete_and_reopen + execsql { + PRAGMA journal_mode = WAL; + CREATE TABLE abc(a PRIMARY KEY); + INSERT INTO abc VALUES(randomblob(900)); + } + faultsim_save_and_close +} {} +do_faultsim_test walfault-9 -prep { + #if {$iFail<73} { set iFail 73 } + #if {$iFail>73} { exit } + + faultsim_restore_and_reopen + execsql { PRAGMA cache_size = 10 } +} -body { + execsql { + BEGIN; + INSERT INTO abc SELECT randomblob(900) FROM abc; /* 1 */ + SAVEPOINT spoint; + INSERT INTO abc SELECT randomblob(900) FROM abc; /* 2 */ + INSERT INTO abc SELECT randomblob(900) FROM abc; /* 4 */ + INSERT INTO abc SELECT randomblob(900) FROM abc; /* 8 */ + ROLLBACK TO spoint; + COMMIT; + SELECT count(*) FROM abc; + } +} -test { + faultsim_test_result {0 2} + faultsim_integrity_check + + catch { db eval { ROLLBACK TO spoint } } + catch { db eval { COMMIT } } + set n [db one {SELECT count(*) FROM abc}] + if {$n != 1 && $n != 2} { error "Incorrect number of rows: $n" } } #------------------------------------------------------------------------- @@ -358,7 +349,8 @@ proc shmfault_vfs_cb_6 {method args} { } do_test walfault-shm-6.1 { set ::shm_state 0 - testvfs tvfs shmfault_vfs_cb_6 + testvfs tvfs + tvfs script shmfault_vfs_cb_6 sqlite3 db test.db -vfs tvfs sqlite3 db2 test.db -vfs tvfs |