1b19a2bc6Sdrh# 2001 September 15 2ed7c855cSdrh# 3b19a2bc6Sdrh# The author disclaims copyright to this source code. In place of 4b19a2bc6Sdrh# a legal notice, here is a blessing: 5ed7c855cSdrh# 6b19a2bc6Sdrh# May you do good and not evil. 7b19a2bc6Sdrh# May you find forgiveness for yourself and forgive others. 8b19a2bc6Sdrh# May you share freely, never taking more than you give. 9ed7c855cSdrh# 10ed7c855cSdrh#*********************************************************************** 11ed7c855cSdrh# This file attempts to check the library in an out-of-memory situation. 12ed7c855cSdrh# When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special 136d4abfbeSdrh# command (sqlite_malloc_fail N) which causes the N-th malloc to fail. This 14ed7c855cSdrh# special feature is used to see what happens in the library if a malloc 15ed7c855cSdrh# were to really fail due to an out-of-memory situation. 16ed7c855cSdrh# 17*b5f70c2eSdrh# $Id: malloc.test,v 1.6 2004/02/14 01:39:50 drh Exp $ 18ed7c855cSdrh 19ed7c855cSdrhset testdir [file dirname $argv0] 20ed7c855cSdrhsource $testdir/tester.tcl 21ed7c855cSdrh 22ed7c855cSdrh# Only run these tests if memory debugging is turned on. 23ed7c855cSdrh# 24*b5f70c2eSdrhif {[info command sqlite_malloc_stat]==""} { 25ed7c855cSdrh puts "Skipping malloc tests: not compiled with -DMEMORY_DEBUG..." 26ed7c855cSdrh finish_test 27ed7c855cSdrh return 28ed7c855cSdrh} 29ed7c855cSdrh 30ed7c855cSdrhfor {set go 1; set i 1} {$go} {incr i} { 31ed7c855cSdrh do_test malloc-1.$i { 32ed7c855cSdrh sqlite_malloc_fail 0 336d4abfbeSdrh catch {db close} 346d4abfbeSdrh catch {file delete -force test.db} 356d4abfbeSdrh catch {file delete -force test.db-journal} 36ed7c855cSdrh sqlite_malloc_fail $i 376d4abfbeSdrh set v [catch {sqlite db test.db} msg] 386d4abfbeSdrh if {$v} { 396d4abfbeSdrh set msg "" 406d4abfbeSdrh } else { 41ed7c855cSdrh set v [catch {execsql { 42ed7c855cSdrh CREATE TABLE t1( 43ed7c855cSdrh a int, b float, c double, d text, e varchar(20), 44ed7c855cSdrh primary key(a,b,c) 45ed7c855cSdrh ); 46ed7c855cSdrh CREATE INDEX i1 ON t1(a,b); 47ed7c855cSdrh INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there'); 48ed7c855cSdrh INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder'); 49ed7c855cSdrh SELECT * FROM t1; 50d400728aSdrh SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0; 516d4abfbeSdrh DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1); 52ed7c855cSdrh SELECT count(*) FROM t1; 53ed7c855cSdrh }} msg] 546d4abfbeSdrh } 556d4abfbeSdrh set leftover [lindex [sqlite_malloc_stat] 2] 566d4abfbeSdrh if {$leftover>0} { 576d4abfbeSdrh if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 58ed7c855cSdrh set ::go 0 59ed7c855cSdrh set v {1 1} 60ed7c855cSdrh } else { 616d4abfbeSdrh set v2 [expr {$msg=="" || $msg=="out of memory"}] 626d4abfbeSdrh if {!$v2} {puts "\nError message returned: $msg"} 636d4abfbeSdrh lappend v $v2 64ed7c855cSdrh } 65ed7c855cSdrh } {1 1} 66ed7c855cSdrh} 67d400728aSdrh 68d400728aSdrhset fd [open ./data.tmp w] 696d4abfbeSdrhfor {set i 1} {$i<=20} {incr i} { 706d4abfbeSdrh puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}] abcdefghijklmnopqrstuvwxyz" 71d400728aSdrh} 72d400728aSdrhclose $fd 73d400728aSdrh 74d400728aSdrhfor {set go 1; set i 1} {$go} {incr i} { 75d400728aSdrh do_test malloc-2.$i { 76d400728aSdrh sqlite_malloc_fail 0 776d4abfbeSdrh catch {db close} 786d4abfbeSdrh catch {file delete -force test.db} 796d4abfbeSdrh catch {file delete -force test.db-journal} 80d400728aSdrh sqlite_malloc_fail $i 816d4abfbeSdrh set v [catch {sqlite db test.db} msg] 826d4abfbeSdrh if {$v} { 836d4abfbeSdrh set msg "" 846d4abfbeSdrh } else { 85d400728aSdrh set v [catch {execsql { 86d400728aSdrh CREATE TABLE t1(a int, b int, c int); 87d400728aSdrh CREATE INDEX i1 ON t1(a,b); 88d400728aSdrh COPY t1 FROM 'data.tmp'; 896d4abfbeSdrh SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1; 906d4abfbeSdrh UPDATE t1 SET b=b||b||b||b; 91d400728aSdrh UPDATE t1 SET b=a WHERE a in (10,12,22); 926d4abfbeSdrh INSERT INTO t1(c,b,a) VALUES(20,10,5); 936d4abfbeSdrh INSERT INTO t1 SELECT * FROM t1 946d4abfbeSdrh WHERE a IN (SELECT a FROM t1 WHERE a<10); 956d4abfbeSdrh DELETE FROM t1 WHERE a>=10; 96d400728aSdrh DROP INDEX i1; 976d4abfbeSdrh DELETE FROM t1; 98d400728aSdrh }} msg] 996d4abfbeSdrh } 1006d4abfbeSdrh set leftover [lindex [sqlite_malloc_stat] 2] 1016d4abfbeSdrh if {$leftover>0} { 1026d4abfbeSdrh if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 103d400728aSdrh set ::go 0 104d400728aSdrh set v {1 1} 105d400728aSdrh } else { 1066d4abfbeSdrh set v2 [expr {$msg=="" || $msg=="out of memory"}] 1076d4abfbeSdrh if {!$v2} {puts "\nError message returned: $msg"} 1086d4abfbeSdrh lappend v $v2 1096d4abfbeSdrh } 1106d4abfbeSdrh } {1 1} 1116d4abfbeSdrh} 1126d4abfbeSdrh 1136d4abfbeSdrhset fd [open ./data.tmp w] 1146d4abfbeSdrhfor {set i 1} {$i<=10} {incr i} { 1156d4abfbeSdrh puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}]" 1166d4abfbeSdrh} 1176d4abfbeSdrhclose $fd 1186d4abfbeSdrh 1196d4abfbeSdrhfor {set go 1; set i 1} {$go} {incr i} { 1206d4abfbeSdrh do_test malloc-3.$i { 1216d4abfbeSdrh sqlite_malloc_fail 0 1226d4abfbeSdrh catch {db close} 1236d4abfbeSdrh catch {file delete -force test.db} 1246d4abfbeSdrh catch {file delete -force test.db-journal} 1256d4abfbeSdrh sqlite_malloc_fail $i 1266d4abfbeSdrh set v [catch {sqlite db test.db} msg] 1276d4abfbeSdrh if {$v} { 1286d4abfbeSdrh set msg "" 1296d4abfbeSdrh } else { 1306d4abfbeSdrh set v [catch {execsql { 1316d4abfbeSdrh BEGIN TRANSACTION; 1326d4abfbeSdrh CREATE TABLE t1(a int, b int, c int); 1336d4abfbeSdrh CREATE INDEX i1 ON t1(a,b); 1346d4abfbeSdrh COPY t1 FROM 'data.tmp'; 1356d4abfbeSdrh INSERT INTO t1(c,b,a) VALUES(20,10,5); 1366d4abfbeSdrh DELETE FROM t1 WHERE a>=10; 1376d4abfbeSdrh DROP INDEX i1; 1386d4abfbeSdrh DELETE FROM t1; 1396d4abfbeSdrh ROLLBACK; 1406d4abfbeSdrh }} msg] 1416d4abfbeSdrh } 1426d4abfbeSdrh set leftover [lindex [sqlite_malloc_stat] 2] 1436d4abfbeSdrh if {$leftover>0} { 1446d4abfbeSdrh if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 1456d4abfbeSdrh set ::go 0 1466d4abfbeSdrh set v {1 1} 1476d4abfbeSdrh } else { 1486d4abfbeSdrh set v2 [expr {$msg=="" || $msg=="out of memory"}] 1496d4abfbeSdrh if {!$v2} {puts "\nError message returned: $msg"} 1506d4abfbeSdrh lappend v $v2 1516d4abfbeSdrh } 1526d4abfbeSdrh } {1 1} 1536d4abfbeSdrh} 1546d4abfbeSdrhfor {set go 1; set i 1} {$go} {incr i} { 1556d4abfbeSdrh do_test malloc-4.$i { 1566d4abfbeSdrh sqlite_malloc_fail 0 1576d4abfbeSdrh catch {db close} 1586d4abfbeSdrh catch {file delete -force test.db} 1596d4abfbeSdrh catch {file delete -force test.db-journal} 1606d4abfbeSdrh sqlite_malloc_fail $i 1616d4abfbeSdrh set v [catch {sqlite db test.db} msg] 1626d4abfbeSdrh if {$v} { 1636d4abfbeSdrh set msg "" 1646d4abfbeSdrh } else { 1656d4abfbeSdrh set v [catch {execsql { 1666d4abfbeSdrh BEGIN TRANSACTION; 1676d4abfbeSdrh CREATE TABLE t1(a int, b int, c int); 1686d4abfbeSdrh CREATE INDEX i1 ON t1(a,b); 1696d4abfbeSdrh COPY t1 FROM 'data.tmp'; 1706d4abfbeSdrh UPDATE t1 SET b=a WHERE a in (10,12,22); 1716d4abfbeSdrh INSERT INTO t1 SELECT * FROM t1 1726d4abfbeSdrh WHERE a IN (SELECT a FROM t1 WHERE a<10); 1736d4abfbeSdrh DROP INDEX i1; 1746d4abfbeSdrh DELETE FROM t1; 1756d4abfbeSdrh COMMIT; 1766d4abfbeSdrh }} msg] 1776d4abfbeSdrh } 1786d4abfbeSdrh set leftover [lindex [sqlite_malloc_stat] 2] 1796d4abfbeSdrh if {$leftover>0} { 1806d4abfbeSdrh if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 1816d4abfbeSdrh set ::go 0 1826d4abfbeSdrh set v {1 1} 1836d4abfbeSdrh } else { 1846d4abfbeSdrh set v2 [expr {$msg=="" || $msg=="out of memory"}] 1856d4abfbeSdrh if {!$v2} {puts "\nError message returned: $msg"} 1866d4abfbeSdrh lappend v $v2 187d400728aSdrh } 188d400728aSdrh } {1 1} 189d400728aSdrh} 190e4697f5eSdrhfor {set go 1; set i 1} {$go} {incr i} { 191e4697f5eSdrh do_test malloc-5.$i { 192e4697f5eSdrh sqlite_malloc_fail 0 193e4697f5eSdrh catch {db close} 194e4697f5eSdrh catch {file delete -force test.db} 195e4697f5eSdrh catch {file delete -force test.db-journal} 196e4697f5eSdrh sqlite_malloc_fail $i 197e4697f5eSdrh set v [catch {sqlite db test.db} msg] 198e4697f5eSdrh if {$v} { 199e4697f5eSdrh set msg "" 200e4697f5eSdrh } else { 201e4697f5eSdrh set v [catch {execsql { 202e4697f5eSdrh BEGIN TRANSACTION; 203e4697f5eSdrh CREATE TABLE t1(a,b); 204e4697f5eSdrh CREATE TABLE t2(x,y); 205e4697f5eSdrh CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN 206e4697f5eSdrh INSERT INTO t2(x,y) VALUES(new.rowid,1); 207e4697f5eSdrh END; 208e4697f5eSdrh INSERT INTO t1(a,b) VALUES(2,3); 209e4697f5eSdrh COMMIT; 210e4697f5eSdrh }} msg] 211e4697f5eSdrh } 212e4697f5eSdrh set leftover [lindex [sqlite_malloc_stat] 2] 213e4697f5eSdrh if {$leftover>0} { 214e4697f5eSdrh if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 215e4697f5eSdrh set ::go 0 216e4697f5eSdrh set v {1 1} 217e4697f5eSdrh } else { 218e4697f5eSdrh set v2 [expr {$msg=="" || $msg=="out of memory"}] 219e4697f5eSdrh if {!$v2} {puts "\nError message returned: $msg"} 220e4697f5eSdrh lappend v $v2 221e4697f5eSdrh } 222e4697f5eSdrh } {1 1} 223e4697f5eSdrh} 224ed7c855cSdrhsqlite_malloc_fail 0 225ed7c855cSdrhfinish_test 226