1
2#pragma ident	"%Z%%M%	%I%	%E% SMI"
3
4# 2001 September 15
5#
6# The author disclaims copyright to this source code.  In place of
7# a legal notice, here is a blessing:
8#
9#    May you do good and not evil.
10#    May you find forgiveness for yourself and forgive others.
11#    May you share freely, never taking more than you give.
12#
13#***********************************************************************
14# This file attempts to check the library in an out-of-memory situation.
15# When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special
16# command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
17# special feature is used to see what happens in the library if a malloc
18# were to really fail due to an out-of-memory situation.
19#
20# $Id: malloc.test,v 1.6 2004/02/14 01:39:50 drh Exp $
21
22set testdir [file dirname $argv0]
23source $testdir/tester.tcl
24
25# Only run these tests if memory debugging is turned on.
26#
27if {[info command sqlite_malloc_stat]==""} {
28   puts "Skipping malloc tests: not compiled with -DMEMORY_DEBUG..."
29   finish_test
30   return
31}
32
33for {set go 1; set i 1} {$go} {incr i} {
34  do_test malloc-1.$i {
35     sqlite_malloc_fail 0
36     catch {db close}
37     catch {file delete -force test.db}
38     catch {file delete -force test.db-journal}
39     sqlite_malloc_fail $i
40     set v [catch {sqlite db test.db} msg]
41     if {$v} {
42       set msg ""
43     } else {
44       set v [catch {execsql {
45          CREATE TABLE t1(
46             a int, b float, c double, d text, e varchar(20),
47             primary key(a,b,c)
48          );
49          CREATE INDEX i1 ON t1(a,b);
50          INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there');
51          INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
52          SELECT * FROM t1;
53          SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
54          DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
55          SELECT count(*) FROM t1;
56       }} msg]
57     }
58     set leftover [lindex [sqlite_malloc_stat] 2]
59     if {$leftover>0} {
60       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
61       set ::go 0
62       set v {1 1}
63     } else {
64       set v2 [expr {$msg=="" || $msg=="out of memory"}]
65       if {!$v2} {puts "\nError message returned: $msg"}
66       lappend v $v2
67     }
68  } {1 1}
69}
70
71set fd [open ./data.tmp w]
72for {set i 1} {$i<=20} {incr i} {
73  puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}] abcdefghijklmnopqrstuvwxyz"
74}
75close $fd
76
77for {set go 1; set i 1} {$go} {incr i} {
78  do_test malloc-2.$i {
79     sqlite_malloc_fail 0
80     catch {db close}
81     catch {file delete -force test.db}
82     catch {file delete -force test.db-journal}
83     sqlite_malloc_fail $i
84     set v [catch {sqlite db test.db} msg]
85     if {$v} {
86       set msg ""
87     } else {
88       set v [catch {execsql {
89         CREATE TABLE t1(a int, b int, c int);
90         CREATE INDEX i1 ON t1(a,b);
91         COPY t1 FROM 'data.tmp';
92         SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
93         UPDATE t1 SET b=b||b||b||b;
94         UPDATE t1 SET b=a WHERE a in (10,12,22);
95         INSERT INTO t1(c,b,a) VALUES(20,10,5);
96         INSERT INTO t1 SELECT * FROM t1
97             WHERE a IN (SELECT a FROM t1 WHERE a<10);
98         DELETE FROM t1 WHERE a>=10;
99         DROP INDEX i1;
100         DELETE FROM t1;
101       }} msg]
102     }
103     set leftover [lindex [sqlite_malloc_stat] 2]
104     if {$leftover>0} {
105       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
106       set ::go 0
107       set v {1 1}
108     } else {
109       set v2 [expr {$msg=="" || $msg=="out of memory"}]
110       if {!$v2} {puts "\nError message returned: $msg"}
111       lappend v $v2
112     }
113  } {1 1}
114}
115
116set fd [open ./data.tmp w]
117for {set i 1} {$i<=10} {incr i} {
118  puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}]"
119}
120close $fd
121
122for {set go 1; set i 1} {$go} {incr i} {
123  do_test malloc-3.$i {
124     sqlite_malloc_fail 0
125     catch {db close}
126     catch {file delete -force test.db}
127     catch {file delete -force test.db-journal}
128     sqlite_malloc_fail $i
129     set v [catch {sqlite db test.db} msg]
130     if {$v} {
131       set msg ""
132     } else {
133       set v [catch {execsql {
134         BEGIN TRANSACTION;
135         CREATE TABLE t1(a int, b int, c int);
136         CREATE INDEX i1 ON t1(a,b);
137         COPY t1 FROM 'data.tmp';
138         INSERT INTO t1(c,b,a) VALUES(20,10,5);
139         DELETE FROM t1 WHERE a>=10;
140         DROP INDEX i1;
141         DELETE FROM t1;
142         ROLLBACK;
143       }} msg]
144     }
145     set leftover [lindex [sqlite_malloc_stat] 2]
146     if {$leftover>0} {
147       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
148       set ::go 0
149       set v {1 1}
150     } else {
151       set v2 [expr {$msg=="" || $msg=="out of memory"}]
152       if {!$v2} {puts "\nError message returned: $msg"}
153       lappend v $v2
154     }
155  } {1 1}
156}
157for {set go 1; set i 1} {$go} {incr i} {
158  do_test malloc-4.$i {
159     sqlite_malloc_fail 0
160     catch {db close}
161     catch {file delete -force test.db}
162     catch {file delete -force test.db-journal}
163     sqlite_malloc_fail $i
164     set v [catch {sqlite db test.db} msg]
165     if {$v} {
166       set msg ""
167     } else {
168       set v [catch {execsql {
169         BEGIN TRANSACTION;
170         CREATE TABLE t1(a int, b int, c int);
171         CREATE INDEX i1 ON t1(a,b);
172         COPY t1 FROM 'data.tmp';
173         UPDATE t1 SET b=a WHERE a in (10,12,22);
174         INSERT INTO t1 SELECT * FROM t1
175             WHERE a IN (SELECT a FROM t1 WHERE a<10);
176         DROP INDEX i1;
177         DELETE FROM t1;
178         COMMIT;
179       }} msg]
180     }
181     set leftover [lindex [sqlite_malloc_stat] 2]
182     if {$leftover>0} {
183       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
184       set ::go 0
185       set v {1 1}
186     } else {
187       set v2 [expr {$msg=="" || $msg=="out of memory"}]
188       if {!$v2} {puts "\nError message returned: $msg"}
189       lappend v $v2
190     }
191  } {1 1}
192}
193for {set go 1; set i 1} {$go} {incr i} {
194  do_test malloc-5.$i {
195     sqlite_malloc_fail 0
196     catch {db close}
197     catch {file delete -force test.db}
198     catch {file delete -force test.db-journal}
199     sqlite_malloc_fail $i
200     set v [catch {sqlite db test.db} msg]
201     if {$v} {
202       set msg ""
203     } else {
204       set v [catch {execsql {
205         BEGIN TRANSACTION;
206         CREATE TABLE t1(a,b);
207         CREATE TABLE t2(x,y);
208         CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
209           INSERT INTO t2(x,y) VALUES(new.rowid,1);
210         END;
211         INSERT INTO t1(a,b) VALUES(2,3);
212         COMMIT;
213       }} msg]
214     }
215     set leftover [lindex [sqlite_malloc_stat] 2]
216     if {$leftover>0} {
217       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
218       set ::go 0
219       set v {1 1}
220     } else {
221       set v2 [expr {$msg=="" || $msg=="out of memory"}]
222       if {!$v2} {puts "\nError message returned: $msg"}
223       lappend v $v2
224     }
225  } {1 1}
226}
227sqlite_malloc_fail 0
228finish_test
229