diff options
Diffstat (limited to 'ext/rbu/rbufault.test')
-rw-r--r-- | ext/rbu/rbufault.test | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/ext/rbu/rbufault.test b/ext/rbu/rbufault.test new file mode 100644 index 0000000..d35c389 --- /dev/null +++ b/ext/rbu/rbufault.test @@ -0,0 +1,234 @@ +# 2014 October 22 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +source [file join [file dirname [info script]] rbu_common.tcl] +if_no_rbu_support { finish_test ; return } +source $testdir/malloc_common.tcl +set ::testprefix rbufault + +proc copy_if_exists {src target} { + if {[file exists $src]} { + forcecopy $src $target + } else { + forcedelete $target + } +} + +foreach {tn2 setup sql expect} { + 1 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX t1cb ON t1(c, b); + INSERT INTO t1 VALUES(1, 1, 1); + INSERT INTO t1 VALUES(2, 2, 2); + INSERT INTO t1 VALUES(3, 3, 3); + + CREATE TABLE rbu.data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); + INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.'); + INSERT INTO data_t1 VALUES(4, 4, 4, 0); + } { + SELECT * FROM t1 + } {1 1 1 3 three 3 4 4 4} + + 2 { + CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; + CREATE INDEX t2cb ON t2(c, b); + INSERT INTO t2 VALUES('a', 'a', 'a'); + INSERT INTO t2 VALUES('b', 'b', 'b'); + INSERT INTO t2 VALUES('c', 'c', 'c'); + + CREATE TABLE rbu.data_t2(a, b, c, rbu_control); + INSERT INTO data_t2 VALUES('b', NULL, NULL, 1); + INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.'); + INSERT INTO data_t2 VALUES('d', 'd', 'd', 0); + } { + SELECT * FROM t2 + } {a a a c see c d d d} + + 3 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; + CREATE INDEX t1cb ON t1(c, b); + CREATE INDEX t2cb ON t2(c, b); + + CREATE TABLE rbu.data_t1(a, b, c, rbu_control); + CREATE TABLE rbu.data_t2(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES(1, 2, 3, 0); + INSERT INTO data_t2 VALUES(4, 5, 6, 0); + } { + SELECT * FROM t1 UNION ALL SELECT * FROM t2 + } {1 2 3 4 5 6} + + 4 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE INDEX t1c ON t1(c); + INSERT INTO t1 VALUES('A', 'B', 'C'); + INSERT INTO t1 VALUES('D', 'E', 'F'); + + CREATE TABLE rbu.data_t1(a, b, c, rbu_control); + INSERT INTO data_t1 VALUES('D', NULL, NULL, 1); + INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.'); + INSERT INTO data_t1 VALUES('G', 'H', 'I', 0); + } { + SELECT * FROM t1 ORDER BY a; + } {A Z C G H I} + + 5 { + CREATE TABLE t1(a, b, c); + CREATE INDEX t1c ON t1(c, b); + + CREATE TABLE rbu.data_t1(a, b, c, rbu_rowid, rbu_control); + INSERT INTO data_t1 VALUES('a', 'b', 'c', 1, 0); + INSERT INTO data_t1 VALUES('d', 'e', 'f', '2', 0); + } { + SELECT * FROM t1 ORDER BY a; + } {a b c d e f} + +} { + catch {db close} + forcedelete rbu.db test.db + sqlite3 db test.db + execsql { + PRAGMA encoding = utf16; + ATTACH 'rbu.db' AS rbu; + } + execsql $setup + db close + + forcecopy test.db test.db.bak + forcecopy rbu.db rbu.db.bak + + foreach {tn f reslist} { + 1 oom-tra* { + {0 SQLITE_DONE} + {1 {SQLITE_NOMEM - out of memory}} + {1 SQLITE_NOMEM} + {1 SQLITE_IOERR_NOMEM} + {1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}} + } + + 2 ioerr-* { + {0 SQLITE_DONE} + {1 {SQLITE_IOERR - disk I/O error}} + {1 SQLITE_IOERR} + {1 SQLITE_IOERR_WRITE} + {1 SQLITE_IOERR_READ} + {1 SQLITE_IOERR_FSYNC} + {1 {SQLITE_ERROR - SQL logic error}} + {1 {SQLITE_ERROR - unable to open database: rbu.db}} + {1 {SQLITE_IOERR - unable to open database: rbu.db}} + } + + 3 shmerr-* { + {0 SQLITE_DONE} + {1 {SQLITE_IOERR - disk I/O error}} + {1 SQLITE_IOERR} + } + } { + + catch {db close} + sqlite3_shutdown + set lookaside_config [sqlite3_config_lookaside 0 0] + sqlite3_initialize + autoinstall_test_functions + + do_faultsim_test 2.$tn2 -faults $::f -prep { + catch { db close } + forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal + forcecopy test.db.bak test.db + forcecopy rbu.db.bak rbu.db + } -body { + sqlite3rbu rbu test.db rbu.db + while {[rbu step]=="SQLITE_OK"} {} + rbu close + } -test { + faultsim_test_result {*}$::reslist + if {$testrc==0} { + sqlite3 db test.db + faultsim_integrity_check + set res [db eval $::sql] + if {$res != [list {*}$::expect]} { + puts "" + puts "res: $res" + puts "exp: $expect" + error "data not as expected!" + } + } + } + + catch {db close} + sqlite3_shutdown + sqlite3_config_lookaside {*}$lookaside_config + sqlite3_initialize + autoinstall_test_functions + + + for {set iStep 0} {$iStep<=21} {incr iStep} { + + forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal + + copy_if_exists test.db.bak test.db + copy_if_exists rbu.db.bak rbu.db + + sqlite3rbu rbu test.db rbu.db + for {set x 0} {$x < $::iStep} {incr x} { rbu step } + rbu close + +# sqlite3 x rbu.db ; puts "XYZ [x eval { SELECT * FROM rbu_state } ]" ; x close + + copy_if_exists test.db test.db.bak.2 + copy_if_exists test.db-wal test.db.bak.2-wal + copy_if_exists test.db-oal test.db.bak.2-oal + copy_if_exists rbu.db rbu.db.bak.2 + + do_faultsim_test 3.$tn.$iStep -faults $::f -prep { + catch { db close } + forcedelete test.db-journal test.db-wal rbu.db-journal rbu.db-wal + copy_if_exists test.db.bak.2 test.db + copy_if_exists test.db.bak.2-wal test.db-wal + copy_if_exists test.db.bak.2-oal test.db-oal + copy_if_exists rbu.db.bak.2 rbu.db + } -body { + sqlite3rbu rbu test.db rbu.db + rbu step + rbu close + } -test { + + if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"} + faultsim_test_result {*}$::reslist + + if {$testrc==0} { + # No error occurred. If the RBU has not already been fully applied, + # apply the rest of it now. Then ensure that the final state of the + # target db is as expected. And that "PRAGMA integrity_check" + # passes. + sqlite3rbu rbu test.db rbu.db + while {[rbu step] == "SQLITE_OK"} {} + rbu close + + sqlite3 db test.db + faultsim_integrity_check + + set res [db eval $::sql] + if {$res != [list {*}$::expect]} { + puts "" + puts "res: $res" + puts "exp: $::expect" + error "data not as expected!" + } + } + } + } + } +} + +finish_test |