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