Index: third_party/sqlite/src/test/malloc3.test |
diff --git a/third_party/sqlite/src/test/malloc3.test b/third_party/sqlite/src/test/malloc3.test |
index 73d2d39642f24ed49c97b31bc46cd590c9f70fcd..f4a6c3bbe90873390c72dbcb8c2d2f580f43b9dc 100644 |
--- a/third_party/sqlite/src/test/malloc3.test |
+++ b/third_party/sqlite/src/test/malloc3.test |
@@ -27,6 +27,24 @@ if {!$MEMDEBUG} { |
return |
} |
+ |
+# Do not run these tests with an in-memory journal. |
+# |
+# In the pager layer, if an IO or OOM error occurs during a ROLLBACK, or |
+# when flushing a page to disk due to cache-stress, the pager enters an |
+# "error state". The only way out of the error state is to unlock the |
+# database file and end the transaction, leaving whatever journal and |
+# database files happen to be on disk in place. The next time the current |
+# (or any other) connection opens a read transaction, hot-journal rollback |
+# is performed if necessary. |
+# |
+# Of course, this doesn't work with an in-memory journal. |
+# |
+if {[permutation]=="inmemory_journal"} { |
+ finish_test |
+ return |
+} |
+ |
#-------------------------------------------------------------------------- |
# NOTES ON RECOVERING FROM A MALLOC FAILURE |
# |
@@ -147,6 +165,7 @@ if {!$MEMDEBUG} { |
# ::run_test_script. At the end of this file, the proc [run_test] is used |
# to execute the program (and all test cases contained therein). |
# |
+set ::run_test_sql_id 0 |
set ::run_test_script [list] |
proc TEST {id t} {lappend ::run_test_script -test [list $id $t]} |
proc PREP {p} {lappend ::run_test_script -prep [string trim $p]} |
@@ -162,13 +181,14 @@ proc DEBUG {s} {lappend ::run_test_script -debug $s} |
# transaction only. |
# |
proc SQL {a1 {a2 ""}} { |
- # An SQL primitive parameter is a list of two elements, a boolean value |
- # indicating if the statement may cause transaction rollback when malloc() |
- # fails, and the sql statement itself. |
+ # An SQL primitive parameter is a list of three elements, an id, a boolean |
+ # value indicating if the statement may cause transaction rollback when |
+ # malloc() fails, and the sql statement itself. |
+ set id [incr ::run_test_sql_id] |
if {$a2 == ""} { |
- lappend ::run_test_script -sql [list true [string trim $a1]] |
+ lappend ::run_test_script -sql [list $id true [string trim $a1]] |
} else { |
- lappend ::run_test_script -sql [list false [string trim $a2]] |
+ lappend ::run_test_script -sql [list $id false [string trim $a2]] |
} |
} |
@@ -258,7 +278,7 @@ TEST 5 { |
set sql { |
BEGIN;DELETE FROM abc; |
} |
-for {set i 1} {$i < 15} {incr i} { |
+for {set i 1} {$i < 100} {incr i} { |
set a $i |
set b "String value $i" |
set c [string repeat X $i] |
@@ -463,7 +483,7 @@ TEST 29 { |
# Test a simple multi-file transaction |
# |
-file delete -force test2.db |
+forcedelete test2.db |
ifcapable attach { |
SQL {ATTACH 'test2.db' AS aux;} |
SQL {BEGIN} |
@@ -529,12 +549,13 @@ proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} { |
} |
for {set i 0} {$i < $pcstart} {incr i} { |
- set k2 [lindex $arglist [expr 2 * $i]] |
- set v2 [lindex $arglist [expr 2 * $i + 1]] |
+ set k2 [lindex $arglist [expr {2 * $i}]] |
+ set v2 [lindex $arglist [expr {2 * $i + 1}]] |
set ac [sqlite3_get_autocommit $::DB] ;# Auto-Commit |
switch -- $k2 { |
- -sql {db eval [lindex $v2 1]} |
+ -sql {db eval [lindex $v2 2]} |
-prep {db eval $v2} |
+ -debug {eval $v2} |
} |
set nac [sqlite3_get_autocommit $::DB] ;# New Auto-Commit |
if {$ac && !$nac} {set begin_pc $i} |
@@ -545,33 +566,39 @@ proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} { |
set iFail $iFailStart |
set pc $pcstart |
while {$pc*2 < [llength $arglist]} { |
+ # Fetch the current instruction type and payload. |
+ set k [lindex $arglist [expr {2 * $pc}]] |
+ set v [lindex $arglist [expr {2 * $pc + 1}]] |
# Id of this iteration: |
- set k [lindex $arglist [expr 2 * $pc]] |
set iterid "pc=$pc.iFail=$iFail$k" |
- set v [lindex $arglist [expr 2 * $pc + 1]] |
switch -- $k { |
-test { |
foreach {id script} $v {} |
+ set testid "malloc3-(test $id).$iterid" |
+ eval $script |
incr pc |
} |
-sql { |
set ::rollback_hook_count 0 |
+ set id [lindex $v 0] |
+ set testid "malloc3-(integrity $id).$iterid" |
+ |
set ac [sqlite3_get_autocommit $::DB] ;# Auto-Commit |
sqlite3_memdebug_fail $iFail -repeat 0 |
- set rc [catch {db eval [lindex $v 1]} msg] ;# True error occurs |
+ set rc [catch {db eval [lindex $v 2]} msg] ;# True error occurs |
set nac [sqlite3_get_autocommit $::DB] ;# New Auto-Commit |
if {$rc != 0 && $nac && !$ac} { |
# Before [db eval] the auto-commit flag was clear. Now it |
- # is set. Since an error occured we assume this was not a |
- # commit - therefore a rollback occured. Check that the |
+ # is set. Since an error occurred we assume this was not a |
+ # commit - therefore a rollback occurred. Check that the |
# rollback-hook was invoked. |
- do_test malloc3-rollback_hook.$iterid { |
+ do_test malloc3-rollback_hook_count.$iterid { |
set ::rollback_hook_count |
} {1} |
} |
@@ -582,8 +609,9 @@ proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} { |
# calls should be equal to the number of benign failures. |
# Otherwise a malloc() failed and the error was not reported. |
# |
- if {$nFail!=$nBenign} { |
- error "Unreported malloc() failure" |
+ set expr {$nFail!=$nBenign} |
+ if {[expr $expr]} { |
+ error "Unreported malloc() failure, test \"$testid\", $expr" |
} |
if {$ac && !$nac} { |
@@ -595,24 +623,23 @@ proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} { |
incr pc |
set iFail 1 |
- integrity_check "malloc3-(integrity).$iterid" |
+ integrity_check $testid |
} elseif {[regexp {.*out of memory} $msg] || [db errorcode] == 3082} { |
# Out of memory error, as expected. |
# |
- integrity_check "malloc3-(integrity).$iterid" |
+ integrity_check $testid |
incr iFail |
if {$nac && !$ac} { |
- |
- if {![lindex $v 0] && [db errorcode] != 3082} { |
- # error "Statement \"[lindex $v 1]\" caused a rollback" |
+ if {![lindex $v 1] && [db errorcode] != 3082} { |
+ # error "Statement \"[lindex $v 2]\" caused a rollback" |
} |
for {set i $begin_pc} {$i < $pc} {incr i} { |
- set k2 [lindex $arglist [expr 2 * $i]] |
- set v2 [lindex $arglist [expr 2 * $i + 1]] |
+ set k2 [lindex $arglist [expr {2 * $i}]] |
+ set v2 [lindex $arglist [expr {2 * $i + 1}]] |
set catchupsql "" |
switch -- $k2 { |
- -sql {set catchupsql [lindex $v2 1]} |
+ -sql {set catchupsql [lindex $v2 2]} |
-prep {set catchupsql $v2} |
} |
db eval $catchupsql |
@@ -622,7 +649,8 @@ proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} { |
error $msg |
} |
- while {[lindex $arglist [expr 2 * ($pc -1)]] == "-test"} { |
+ # back up to the previous "-test" block. |
+ while {[lindex $arglist [expr {2 * ($pc - 1)}]] == "-test"} { |
incr pc -1 |
} |
} |
@@ -642,7 +670,7 @@ proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} { |
} |
} |
-# Turn of the Tcl interface's prepared statement caching facility. Then |
+# Turn off the Tcl interface's prepared statement caching facility. Then |
# run the tests with "persistent" malloc failures. |
sqlite3_extended_result_codes db 1 |
db cache size 0 |
@@ -650,7 +678,7 @@ run_test $::run_test_script 1 |
# Close and reopen the db. |
db close |
-file delete -force test.db test.db-journal test2.db test2.db-journal |
+forcedelete test.db test.db-journal test2.db test2.db-journal |
sqlite3 db test.db |
sqlite3_extended_result_codes db 1 |
set ::DB [sqlite3_connection_pointer db] |