1*1da57d55SToomas Soome# 27c478bd9Sstevel@tonic-gate# 2001 September 15 37c478bd9Sstevel@tonic-gate# 47c478bd9Sstevel@tonic-gate# The author disclaims copyright to this source code. In place of 57c478bd9Sstevel@tonic-gate# a legal notice, here is a blessing: 67c478bd9Sstevel@tonic-gate# 77c478bd9Sstevel@tonic-gate# May you do good and not evil. 87c478bd9Sstevel@tonic-gate# May you find forgiveness for yourself and forgive others. 97c478bd9Sstevel@tonic-gate# May you share freely, never taking more than you give. 107c478bd9Sstevel@tonic-gate# 117c478bd9Sstevel@tonic-gate#*********************************************************************** 127c478bd9Sstevel@tonic-gate# This file attempts to check the library in an out-of-memory situation. 137c478bd9Sstevel@tonic-gate# When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special 147c478bd9Sstevel@tonic-gate# command (sqlite_malloc_fail N) which causes the N-th malloc to fail. This 157c478bd9Sstevel@tonic-gate# special feature is used to see what happens in the library if a malloc 167c478bd9Sstevel@tonic-gate# were to really fail due to an out-of-memory situation. 177c478bd9Sstevel@tonic-gate# 187c478bd9Sstevel@tonic-gate# $Id: malloc.test,v 1.6 2004/02/14 01:39:50 drh Exp $ 197c478bd9Sstevel@tonic-gate 207c478bd9Sstevel@tonic-gateset testdir [file dirname $argv0] 217c478bd9Sstevel@tonic-gatesource $testdir/tester.tcl 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate# Only run these tests if memory debugging is turned on. 247c478bd9Sstevel@tonic-gate# 257c478bd9Sstevel@tonic-gateif {[info command sqlite_malloc_stat]==""} { 267c478bd9Sstevel@tonic-gate puts "Skipping malloc tests: not compiled with -DMEMORY_DEBUG..." 277c478bd9Sstevel@tonic-gate finish_test 287c478bd9Sstevel@tonic-gate return 297c478bd9Sstevel@tonic-gate} 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gatefor {set go 1; set i 1} {$go} {incr i} { 327c478bd9Sstevel@tonic-gate do_test malloc-1.$i { 337c478bd9Sstevel@tonic-gate sqlite_malloc_fail 0 347c478bd9Sstevel@tonic-gate catch {db close} 357c478bd9Sstevel@tonic-gate catch {file delete -force test.db} 367c478bd9Sstevel@tonic-gate catch {file delete -force test.db-journal} 377c478bd9Sstevel@tonic-gate sqlite_malloc_fail $i 387c478bd9Sstevel@tonic-gate set v [catch {sqlite db test.db} msg] 397c478bd9Sstevel@tonic-gate if {$v} { 407c478bd9Sstevel@tonic-gate set msg "" 417c478bd9Sstevel@tonic-gate } else { 427c478bd9Sstevel@tonic-gate set v [catch {execsql { 437c478bd9Sstevel@tonic-gate CREATE TABLE t1( 447c478bd9Sstevel@tonic-gate a int, b float, c double, d text, e varchar(20), 457c478bd9Sstevel@tonic-gate primary key(a,b,c) 467c478bd9Sstevel@tonic-gate ); 477c478bd9Sstevel@tonic-gate CREATE INDEX i1 ON t1(a,b); 487c478bd9Sstevel@tonic-gate INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there'); 497c478bd9Sstevel@tonic-gate INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder'); 507c478bd9Sstevel@tonic-gate SELECT * FROM t1; 517c478bd9Sstevel@tonic-gate SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0; 527c478bd9Sstevel@tonic-gate DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1); 537c478bd9Sstevel@tonic-gate SELECT count(*) FROM t1; 547c478bd9Sstevel@tonic-gate }} msg] 557c478bd9Sstevel@tonic-gate } 567c478bd9Sstevel@tonic-gate set leftover [lindex [sqlite_malloc_stat] 2] 577c478bd9Sstevel@tonic-gate if {$leftover>0} { 587c478bd9Sstevel@tonic-gate if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 597c478bd9Sstevel@tonic-gate set ::go 0 607c478bd9Sstevel@tonic-gate set v {1 1} 617c478bd9Sstevel@tonic-gate } else { 627c478bd9Sstevel@tonic-gate set v2 [expr {$msg=="" || $msg=="out of memory"}] 637c478bd9Sstevel@tonic-gate if {!$v2} {puts "\nError message returned: $msg"} 647c478bd9Sstevel@tonic-gate lappend v $v2 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate } {1 1} 677c478bd9Sstevel@tonic-gate} 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gateset fd [open ./data.tmp w] 707c478bd9Sstevel@tonic-gatefor {set i 1} {$i<=20} {incr i} { 717c478bd9Sstevel@tonic-gate puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}] abcdefghijklmnopqrstuvwxyz" 727c478bd9Sstevel@tonic-gate} 737c478bd9Sstevel@tonic-gateclose $fd 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gatefor {set go 1; set i 1} {$go} {incr i} { 767c478bd9Sstevel@tonic-gate do_test malloc-2.$i { 777c478bd9Sstevel@tonic-gate sqlite_malloc_fail 0 787c478bd9Sstevel@tonic-gate catch {db close} 797c478bd9Sstevel@tonic-gate catch {file delete -force test.db} 807c478bd9Sstevel@tonic-gate catch {file delete -force test.db-journal} 817c478bd9Sstevel@tonic-gate sqlite_malloc_fail $i 827c478bd9Sstevel@tonic-gate set v [catch {sqlite db test.db} msg] 837c478bd9Sstevel@tonic-gate if {$v} { 847c478bd9Sstevel@tonic-gate set msg "" 857c478bd9Sstevel@tonic-gate } else { 867c478bd9Sstevel@tonic-gate set v [catch {execsql { 877c478bd9Sstevel@tonic-gate CREATE TABLE t1(a int, b int, c int); 887c478bd9Sstevel@tonic-gate CREATE INDEX i1 ON t1(a,b); 897c478bd9Sstevel@tonic-gate COPY t1 FROM 'data.tmp'; 907c478bd9Sstevel@tonic-gate SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1; 917c478bd9Sstevel@tonic-gate UPDATE t1 SET b=b||b||b||b; 927c478bd9Sstevel@tonic-gate UPDATE t1 SET b=a WHERE a in (10,12,22); 937c478bd9Sstevel@tonic-gate INSERT INTO t1(c,b,a) VALUES(20,10,5); 947c478bd9Sstevel@tonic-gate INSERT INTO t1 SELECT * FROM t1 957c478bd9Sstevel@tonic-gate WHERE a IN (SELECT a FROM t1 WHERE a<10); 967c478bd9Sstevel@tonic-gate DELETE FROM t1 WHERE a>=10; 977c478bd9Sstevel@tonic-gate DROP INDEX i1; 987c478bd9Sstevel@tonic-gate DELETE FROM t1; 997c478bd9Sstevel@tonic-gate }} msg] 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate set leftover [lindex [sqlite_malloc_stat] 2] 1027c478bd9Sstevel@tonic-gate if {$leftover>0} { 1037c478bd9Sstevel@tonic-gate if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 1047c478bd9Sstevel@tonic-gate set ::go 0 1057c478bd9Sstevel@tonic-gate set v {1 1} 1067c478bd9Sstevel@tonic-gate } else { 1077c478bd9Sstevel@tonic-gate set v2 [expr {$msg=="" || $msg=="out of memory"}] 1087c478bd9Sstevel@tonic-gate if {!$v2} {puts "\nError message returned: $msg"} 1097c478bd9Sstevel@tonic-gate lappend v $v2 1107c478bd9Sstevel@tonic-gate } 1117c478bd9Sstevel@tonic-gate } {1 1} 1127c478bd9Sstevel@tonic-gate} 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gateset fd [open ./data.tmp w] 1157c478bd9Sstevel@tonic-gatefor {set i 1} {$i<=10} {incr i} { 1167c478bd9Sstevel@tonic-gate puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}]" 1177c478bd9Sstevel@tonic-gate} 1187c478bd9Sstevel@tonic-gateclose $fd 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gatefor {set go 1; set i 1} {$go} {incr i} { 1217c478bd9Sstevel@tonic-gate do_test malloc-3.$i { 1227c478bd9Sstevel@tonic-gate sqlite_malloc_fail 0 1237c478bd9Sstevel@tonic-gate catch {db close} 1247c478bd9Sstevel@tonic-gate catch {file delete -force test.db} 1257c478bd9Sstevel@tonic-gate catch {file delete -force test.db-journal} 1267c478bd9Sstevel@tonic-gate sqlite_malloc_fail $i 1277c478bd9Sstevel@tonic-gate set v [catch {sqlite db test.db} msg] 1287c478bd9Sstevel@tonic-gate if {$v} { 1297c478bd9Sstevel@tonic-gate set msg "" 1307c478bd9Sstevel@tonic-gate } else { 1317c478bd9Sstevel@tonic-gate set v [catch {execsql { 1327c478bd9Sstevel@tonic-gate BEGIN TRANSACTION; 1337c478bd9Sstevel@tonic-gate CREATE TABLE t1(a int, b int, c int); 1347c478bd9Sstevel@tonic-gate CREATE INDEX i1 ON t1(a,b); 1357c478bd9Sstevel@tonic-gate COPY t1 FROM 'data.tmp'; 1367c478bd9Sstevel@tonic-gate INSERT INTO t1(c,b,a) VALUES(20,10,5); 1377c478bd9Sstevel@tonic-gate DELETE FROM t1 WHERE a>=10; 1387c478bd9Sstevel@tonic-gate DROP INDEX i1; 1397c478bd9Sstevel@tonic-gate DELETE FROM t1; 1407c478bd9Sstevel@tonic-gate ROLLBACK; 1417c478bd9Sstevel@tonic-gate }} msg] 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate set leftover [lindex [sqlite_malloc_stat] 2] 1447c478bd9Sstevel@tonic-gate if {$leftover>0} { 1457c478bd9Sstevel@tonic-gate if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 1467c478bd9Sstevel@tonic-gate set ::go 0 1477c478bd9Sstevel@tonic-gate set v {1 1} 1487c478bd9Sstevel@tonic-gate } else { 1497c478bd9Sstevel@tonic-gate set v2 [expr {$msg=="" || $msg=="out of memory"}] 1507c478bd9Sstevel@tonic-gate if {!$v2} {puts "\nError message returned: $msg"} 1517c478bd9Sstevel@tonic-gate lappend v $v2 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate } {1 1} 1547c478bd9Sstevel@tonic-gate} 1557c478bd9Sstevel@tonic-gatefor {set go 1; set i 1} {$go} {incr i} { 1567c478bd9Sstevel@tonic-gate do_test malloc-4.$i { 1577c478bd9Sstevel@tonic-gate sqlite_malloc_fail 0 1587c478bd9Sstevel@tonic-gate catch {db close} 1597c478bd9Sstevel@tonic-gate catch {file delete -force test.db} 1607c478bd9Sstevel@tonic-gate catch {file delete -force test.db-journal} 1617c478bd9Sstevel@tonic-gate sqlite_malloc_fail $i 1627c478bd9Sstevel@tonic-gate set v [catch {sqlite db test.db} msg] 1637c478bd9Sstevel@tonic-gate if {$v} { 1647c478bd9Sstevel@tonic-gate set msg "" 1657c478bd9Sstevel@tonic-gate } else { 1667c478bd9Sstevel@tonic-gate set v [catch {execsql { 1677c478bd9Sstevel@tonic-gate BEGIN TRANSACTION; 1687c478bd9Sstevel@tonic-gate CREATE TABLE t1(a int, b int, c int); 1697c478bd9Sstevel@tonic-gate CREATE INDEX i1 ON t1(a,b); 1707c478bd9Sstevel@tonic-gate COPY t1 FROM 'data.tmp'; 1717c478bd9Sstevel@tonic-gate UPDATE t1 SET b=a WHERE a in (10,12,22); 1727c478bd9Sstevel@tonic-gate INSERT INTO t1 SELECT * FROM t1 1737c478bd9Sstevel@tonic-gate WHERE a IN (SELECT a FROM t1 WHERE a<10); 1747c478bd9Sstevel@tonic-gate DROP INDEX i1; 1757c478bd9Sstevel@tonic-gate DELETE FROM t1; 1767c478bd9Sstevel@tonic-gate COMMIT; 1777c478bd9Sstevel@tonic-gate }} msg] 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate set leftover [lindex [sqlite_malloc_stat] 2] 1807c478bd9Sstevel@tonic-gate if {$leftover>0} { 1817c478bd9Sstevel@tonic-gate if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 1827c478bd9Sstevel@tonic-gate set ::go 0 1837c478bd9Sstevel@tonic-gate set v {1 1} 1847c478bd9Sstevel@tonic-gate } else { 1857c478bd9Sstevel@tonic-gate set v2 [expr {$msg=="" || $msg=="out of memory"}] 1867c478bd9Sstevel@tonic-gate if {!$v2} {puts "\nError message returned: $msg"} 1877c478bd9Sstevel@tonic-gate lappend v $v2 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate } {1 1} 1907c478bd9Sstevel@tonic-gate} 1917c478bd9Sstevel@tonic-gatefor {set go 1; set i 1} {$go} {incr i} { 1927c478bd9Sstevel@tonic-gate do_test malloc-5.$i { 1937c478bd9Sstevel@tonic-gate sqlite_malloc_fail 0 1947c478bd9Sstevel@tonic-gate catch {db close} 1957c478bd9Sstevel@tonic-gate catch {file delete -force test.db} 1967c478bd9Sstevel@tonic-gate catch {file delete -force test.db-journal} 1977c478bd9Sstevel@tonic-gate sqlite_malloc_fail $i 1987c478bd9Sstevel@tonic-gate set v [catch {sqlite db test.db} msg] 1997c478bd9Sstevel@tonic-gate if {$v} { 2007c478bd9Sstevel@tonic-gate set msg "" 2017c478bd9Sstevel@tonic-gate } else { 2027c478bd9Sstevel@tonic-gate set v [catch {execsql { 2037c478bd9Sstevel@tonic-gate BEGIN TRANSACTION; 2047c478bd9Sstevel@tonic-gate CREATE TABLE t1(a,b); 2057c478bd9Sstevel@tonic-gate CREATE TABLE t2(x,y); 2067c478bd9Sstevel@tonic-gate CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN 2077c478bd9Sstevel@tonic-gate INSERT INTO t2(x,y) VALUES(new.rowid,1); 2087c478bd9Sstevel@tonic-gate END; 2097c478bd9Sstevel@tonic-gate INSERT INTO t1(a,b) VALUES(2,3); 2107c478bd9Sstevel@tonic-gate COMMIT; 2117c478bd9Sstevel@tonic-gate }} msg] 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate set leftover [lindex [sqlite_malloc_stat] 2] 2147c478bd9Sstevel@tonic-gate if {$leftover>0} { 2157c478bd9Sstevel@tonic-gate if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 2167c478bd9Sstevel@tonic-gate set ::go 0 2177c478bd9Sstevel@tonic-gate set v {1 1} 2187c478bd9Sstevel@tonic-gate } else { 2197c478bd9Sstevel@tonic-gate set v2 [expr {$msg=="" || $msg=="out of memory"}] 2207c478bd9Sstevel@tonic-gate if {!$v2} {puts "\nError message returned: $msg"} 2217c478bd9Sstevel@tonic-gate lappend v $v2 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate } {1 1} 2247c478bd9Sstevel@tonic-gate} 2257c478bd9Sstevel@tonic-gatesqlite_malloc_fail 0 2267c478bd9Sstevel@tonic-gatefinish_test 227