blob: 9b117b68e9fac7776a0c6dd6d2f66fb264eba83f [file] [log] [blame]
drhb19a2bc2001-09-16 00:13:26 +00001# 2001 September 15
drhed7c8552001-04-11 14:29:21 +00002#
drhb19a2bc2001-09-16 00:13:26 +00003# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
drhed7c8552001-04-11 14:29:21 +00005#
drhb19a2bc2001-09-16 00:13:26 +00006# May you do good and not evil.
7# May you find forgiveness for yourself and forgive others.
8# May you share freely, never taking more than you give.
drhed7c8552001-04-11 14:29:21 +00009#
10#***********************************************************************
11# This file attempts to check the library in an out-of-memory situation.
drhc89b91b2005-01-03 01:32:59 +000012# When compiled with -DSQLITE_DEBUG=1, the SQLite library accepts a special
drh6d4abfb2001-10-22 02:58:08 +000013# command (sqlite_malloc_fail N) which causes the N-th malloc to fail. This
drhed7c8552001-04-11 14:29:21 +000014# special feature is used to see what happens in the library if a malloc
15# were to really fail due to an out-of-memory situation.
16#
danielk19778b60e0f2005-01-12 09:10:39 +000017# $Id: malloc.test,v 1.15 2005/01/12 09:10:41 danielk1977 Exp $
drhed7c8552001-04-11 14:29:21 +000018
19set testdir [file dirname $argv0]
20source $testdir/tester.tcl
21
22# Only run these tests if memory debugging is turned on.
23#
drhb5f70c22004-02-14 01:39:50 +000024if {[info command sqlite_malloc_stat]==""} {
drhc89b91b2005-01-03 01:32:59 +000025 puts "Skipping malloc tests: not compiled with -DSQLITE_DEBUG..."
drhed7c8552001-04-11 14:29:21 +000026 finish_test
27 return
28}
29
30for {set go 1; set i 1} {$go} {incr i} {
31 do_test malloc-1.$i {
32 sqlite_malloc_fail 0
drh6d4abfb2001-10-22 02:58:08 +000033 catch {db close}
34 catch {file delete -force test.db}
35 catch {file delete -force test.db-journal}
drh46934232004-11-20 19:18:00 +000036 sqlite_malloc_fail $i [expr {$i%4}]
drhef4ac8f2004-06-19 00:16:31 +000037 set v [catch {sqlite3 db test.db} msg]
drh6d4abfb2001-10-22 02:58:08 +000038 if {$v} {
39 set msg ""
40 } else {
41 set v [catch {execsql {
42 CREATE TABLE t1(
43 a int, b float, c double, d text, e varchar(20),
44 primary key(a,b,c)
45 );
46 CREATE INDEX i1 ON t1(a,b);
47 INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there');
48 INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
49 SELECT * FROM t1;
50 SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
51 DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
52 SELECT count(*) FROM t1;
53 }} msg]
54 }
55 set leftover [lindex [sqlite_malloc_stat] 2]
56 if {$leftover>0} {
57 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
drhed7c8552001-04-11 14:29:21 +000058 set ::go 0
59 set v {1 1}
60 } else {
drh6d4abfb2001-10-22 02:58:08 +000061 set v2 [expr {$msg=="" || $msg=="out of memory"}]
62 if {!$v2} {puts "\nError message returned: $msg"}
63 lappend v $v2
drhed7c8552001-04-11 14:29:21 +000064 }
65 } {1 1}
66}
drhd4007282001-04-12 23:21:58 +000067
danielk1977b5548a82004-06-26 13:51:33 +000068# Ensure that no file descriptors were leaked.
69do_test malloc-1.X {
70 catch {db close}
71 set sqlite_open_file_count
72} {0}
73
drhd4007282001-04-12 23:21:58 +000074set fd [open ./data.tmp w]
drh6d4abfb2001-10-22 02:58:08 +000075for {set i 1} {$i<=20} {incr i} {
drh5f3b4ab2004-05-27 17:22:54 +000076 puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}] abcdefghijklmnopqrstuvwxyz"
drhd4007282001-04-12 23:21:58 +000077}
78close $fd
79
80for {set go 1; set i 1} {$go} {incr i} {
81 do_test malloc-2.$i {
82 sqlite_malloc_fail 0
drh6d4abfb2001-10-22 02:58:08 +000083 catch {db close}
84 catch {file delete -force test.db}
85 catch {file delete -force test.db-journal}
drhd4007282001-04-12 23:21:58 +000086 sqlite_malloc_fail $i
drhef4ac8f2004-06-19 00:16:31 +000087 set v [catch {sqlite3 db test.db} msg]
drh6d4abfb2001-10-22 02:58:08 +000088 if {$v} {
89 set msg ""
90 } else {
91 set v [catch {execsql {
92 CREATE TABLE t1(a int, b int, c int);
93 CREATE INDEX i1 ON t1(a,b);
drh5f3b4ab2004-05-27 17:22:54 +000094 INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz');
95 INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz');
96 INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz');
97 INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz');
98 INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz');
99 INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz');
drh6d4abfb2001-10-22 02:58:08 +0000100 SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
101 UPDATE t1 SET b=b||b||b||b;
102 UPDATE t1 SET b=a WHERE a in (10,12,22);
103 INSERT INTO t1(c,b,a) VALUES(20,10,5);
104 INSERT INTO t1 SELECT * FROM t1
105 WHERE a IN (SELECT a FROM t1 WHERE a<10);
106 DELETE FROM t1 WHERE a>=10;
107 DROP INDEX i1;
108 DELETE FROM t1;
109 }} msg]
110 }
111 set leftover [lindex [sqlite_malloc_stat] 2]
112 if {$leftover>0} {
113 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
drhd4007282001-04-12 23:21:58 +0000114 set ::go 0
115 set v {1 1}
116 } else {
drh6d4abfb2001-10-22 02:58:08 +0000117 set v2 [expr {$msg=="" || $msg=="out of memory"}]
118 if {!$v2} {puts "\nError message returned: $msg"}
119 lappend v $v2
120 }
121 } {1 1}
122}
123
danielk1977b5548a82004-06-26 13:51:33 +0000124# Ensure that no file descriptors were leaked.
125do_test malloc-2.X {
126 catch {db close}
127 set sqlite_open_file_count
128} {0}
129
drh6d4abfb2001-10-22 02:58:08 +0000130for {set go 1; set i 1} {$go} {incr i} {
131 do_test malloc-3.$i {
132 sqlite_malloc_fail 0
133 catch {db close}
134 catch {file delete -force test.db}
135 catch {file delete -force test.db-journal}
136 sqlite_malloc_fail $i
drhef4ac8f2004-06-19 00:16:31 +0000137 set v [catch {sqlite3 db test.db} msg]
drh6d4abfb2001-10-22 02:58:08 +0000138 if {$v} {
139 set msg ""
140 } else {
141 set v [catch {execsql {
142 BEGIN TRANSACTION;
143 CREATE TABLE t1(a int, b int, c int);
144 CREATE INDEX i1 ON t1(a,b);
drh5f3b4ab2004-05-27 17:22:54 +0000145 INSERT INTO t1 VALUES(1,1,99);
146 INSERT INTO t1 VALUES(2,4,98);
147 INSERT INTO t1 VALUES(3,9,97);
148 INSERT INTO t1 VALUES(4,16,96);
149 INSERT INTO t1 VALUES(5,25,95);
150 INSERT INTO t1 VALUES(6,36,94);
drh6d4abfb2001-10-22 02:58:08 +0000151 INSERT INTO t1(c,b,a) VALUES(20,10,5);
152 DELETE FROM t1 WHERE a>=10;
153 DROP INDEX i1;
154 DELETE FROM t1;
155 ROLLBACK;
156 }} msg]
157 }
158 set leftover [lindex [sqlite_malloc_stat] 2]
159 if {$leftover>0} {
160 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
161 set ::go 0
162 set v {1 1}
163 } else {
164 set v2 [expr {$msg=="" || $msg=="out of memory"}]
165 if {!$v2} {puts "\nError message returned: $msg"}
166 lappend v $v2
167 }
168 } {1 1}
169}
danielk1977b5548a82004-06-26 13:51:33 +0000170
171# Ensure that no file descriptors were leaked.
172do_test malloc-3.X {
173 catch {db close}
174 set sqlite_open_file_count
175} {0}
176
drh6d4abfb2001-10-22 02:58:08 +0000177for {set go 1; set i 1} {$go} {incr i} {
178 do_test malloc-4.$i {
179 sqlite_malloc_fail 0
180 catch {db close}
181 catch {file delete -force test.db}
182 catch {file delete -force test.db-journal}
183 sqlite_malloc_fail $i
drhef4ac8f2004-06-19 00:16:31 +0000184 set v [catch {sqlite3 db test.db} msg]
drh6d4abfb2001-10-22 02:58:08 +0000185 if {$v} {
186 set msg ""
187 } else {
188 set v [catch {execsql {
189 BEGIN TRANSACTION;
190 CREATE TABLE t1(a int, b int, c int);
191 CREATE INDEX i1 ON t1(a,b);
drh5f3b4ab2004-05-27 17:22:54 +0000192 INSERT INTO t1 VALUES(1,1,99);
193 INSERT INTO t1 VALUES(2,4,98);
194 INSERT INTO t1 VALUES(3,9,97);
195 INSERT INTO t1 VALUES(4,16,96);
196 INSERT INTO t1 VALUES(5,25,95);
197 INSERT INTO t1 VALUES(6,36,94);
drh6d4abfb2001-10-22 02:58:08 +0000198 UPDATE t1 SET b=a WHERE a in (10,12,22);
199 INSERT INTO t1 SELECT * FROM t1
200 WHERE a IN (SELECT a FROM t1 WHERE a<10);
201 DROP INDEX i1;
202 DELETE FROM t1;
203 COMMIT;
204 }} msg]
205 }
206 set leftover [lindex [sqlite_malloc_stat] 2]
207 if {$leftover>0} {
208 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
209 set ::go 0
210 set v {1 1}
211 } else {
212 set v2 [expr {$msg=="" || $msg=="out of memory"}]
213 if {!$v2} {puts "\nError message returned: $msg"}
214 lappend v $v2
drhd4007282001-04-12 23:21:58 +0000215 }
216 } {1 1}
217}
danielk1977b5548a82004-06-26 13:51:33 +0000218
219# Ensure that no file descriptors were leaked.
220do_test malloc-4.X {
221 catch {db close}
222 set sqlite_open_file_count
223} {0}
224
drhe4697f52002-05-23 02:09:03 +0000225for {set go 1; set i 1} {$go} {incr i} {
226 do_test malloc-5.$i {
227 sqlite_malloc_fail 0
228 catch {db close}
229 catch {file delete -force test.db}
230 catch {file delete -force test.db-journal}
231 sqlite_malloc_fail $i
drhef4ac8f2004-06-19 00:16:31 +0000232 set v [catch {sqlite3 db test.db} msg]
drhe4697f52002-05-23 02:09:03 +0000233 if {$v} {
234 set msg ""
235 } else {
236 set v [catch {execsql {
237 BEGIN TRANSACTION;
238 CREATE TABLE t1(a,b);
239 CREATE TABLE t2(x,y);
240 CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
241 INSERT INTO t2(x,y) VALUES(new.rowid,1);
242 END;
243 INSERT INTO t1(a,b) VALUES(2,3);
244 COMMIT;
245 }} msg]
246 }
247 set leftover [lindex [sqlite_malloc_stat] 2]
248 if {$leftover>0} {
249 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
250 set ::go 0
251 set v {1 1}
252 } else {
253 set v2 [expr {$msg=="" || $msg=="out of memory"}]
254 if {!$v2} {puts "\nError message returned: $msg"}
255 lappend v $v2
256 }
257 } {1 1}
258}
danielk1977b5548a82004-06-26 13:51:33 +0000259
260# Ensure that no file descriptors were leaked.
261do_test malloc-5.X {
262 catch {db close}
263 set sqlite_open_file_count
264} {0}
265
danielk197796fb0dd2004-06-30 09:49:22 +0000266for {set go 1; set i 1} {$go} {incr i} {
267 do_test malloc-6.$i {
268 sqlite_malloc_fail 0
269 catch {db close}
270 catch {file delete -force test.db}
271 catch {file delete -force test.db-journal}
272 sqlite3 db test.db
273 execsql {
274 BEGIN TRANSACTION;
275 CREATE TABLE t1(a);
276 INSERT INTO t1 VALUES(1);
277 INSERT INTO t1 SELECT a*2 FROM t1;
278 INSERT INTO t1 SELECT a*2 FROM t1;
279 INSERT INTO t1 SELECT a*2 FROM t1;
280 INSERT INTO t1 SELECT a*2 FROM t1;
281 INSERT INTO t1 SELECT a*2 FROM t1;
282 INSERT INTO t1 SELECT a*2 FROM t1;
283 INSERT INTO t1 SELECT a*2 FROM t1;
284 INSERT INTO t1 SELECT a*2 FROM t1;
285 INSERT INTO t1 SELECT a*2 FROM t1;
286 INSERT INTO t1 SELECT a*2 FROM t1;
287 DELETE FROM t1 where rowid%5 = 0;
288 COMMIT;
289 }
290 sqlite_malloc_fail $i
291 set v [catch {execsql {
292 VACUUM;
293 }} msg]
294 set leftover [lindex [sqlite_malloc_stat] 2]
295 if {$leftover>0} {
296 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
297 set ::go 0
298 set v {1 1}
299 } else {
300 set v2 [expr {$msg=="" || $msg=="out of memory"}]
301 if {!$v2} {puts "\nError message returned: $msg"}
302 lappend v $v2
303 }
304 } {1 1}
305}
306
danielk197701427a62005-01-11 13:02:33 +0000307for {set go 1; set i 1} {$go} {incr i} {
308 do_test malloc-7.$i {
309 sqlite_malloc_fail 0
310 catch {db close}
311 catch {file delete -force test.db}
312 catch {file delete -force test.db-journal}
313 sqlite3 db test.db
314 execsql {
315 CREATE TABLE t1(a, b);
316 INSERT INTO t1 VALUES(1, 2);
317 INSERT INTO t1 VALUES(3, 4);
318 INSERT INTO t1 VALUES(5, 6);
danielk1977b5402fb2005-01-12 07:15:04 +0000319 INSERT INTO t1 VALUES(7, randstr(1200,1200));
danielk197701427a62005-01-11 13:02:33 +0000320 }
321 sqlite_malloc_fail $i
322 set v [catch {execsql {
danielk1977b5402fb2005-01-12 07:15:04 +0000323 SELECT min(a) FROM t1 WHERE a<6 GROUP BY b;
324 SELECT a FROM t1 WHERE a<6 ORDER BY a;
325 SELECT b FROM t1 WHERE a>6;
danielk197701427a62005-01-11 13:02:33 +0000326 }} msg]
327 set leftover [lindex [sqlite_malloc_stat] 2]
328 if {$leftover>0} {
329 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
330 set ::go 0
331 set v {1 1}
332 } else {
333 set v2 [expr {$msg=="" || $msg=="out of memory"}]
334 if {!$v2} {puts "\nError message returned: $msg"}
335 lappend v $v2
336 }
337 } {1 1}
338}
339
danielk1977b5402fb2005-01-12 07:15:04 +0000340# This block is designed to test that some malloc failures that may
341# occur in vdbeapi.c. Specifically, if a malloc failure that occurs
342# when converting UTF-16 text to integers and real numbers is handled
343# correctly.
344#
danielk19778b60e0f2005-01-12 09:10:39 +0000345# This is done by retrieving a string from the database engine and
346# manipulating it using the sqlite3_column_*** APIs. This doesn't
347# actually return an error to the user when a malloc() fails.. That
348# could be viewed as a bug.
349#
350# These tests only run if UTF-16 support is compiled in.
danielk1977b5402fb2005-01-12 07:15:04 +0000351#
352for {set go 1; set i 1} {$go && $::sqlite_options(utf16)} {incr i} {
353 do_test malloc-8.$i {
354 sqlite_malloc_fail 0
355 catch {db close}
356 catch {file delete -force test.db}
357 catch {file delete -force test.db-journal}
358
359 set ::DB [sqlite3 db test.db]
360 set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?"
361 set ::STMT [sqlite3_prepare $::DB $sql -1 X]
362 sqlite3_step $::STMT
363
364 if { $::tcl_platform(byteOrder)=="littleEndian" } {
365 set ::bomstr "\xFF\xFE"
366 } else {
367 set ::bomstr "\xFE\xFF"
368 }
369 append ::bomstr [encoding convertto unicode "123456789_123456789_12345678"]
370
371 sqlite_malloc_fail $i
372 catch {
373 sqlite3_column_text16 $::STMT 0
374 sqlite3_column_int $::STMT 0
375 sqlite3_column_text16 $::STMT 1
376 sqlite3_column_double $::STMT 1
377 sqlite3_reset $::STMT
378 sqlite3_bind_text16 $::STMT 1 $::bomstr 60
379
380 } msg
381 sqlite3_finalize $::STMT
382 if {[lindex [sqlite_malloc_stat] 2]>0} {
383 set ::go 0
384 }
385 expr 0
386 } {0}
387}
388
danielk19778b60e0f2005-01-12 09:10:39 +0000389# This block tests that malloc() failures that occur whilst commiting
390# a multi-file transaction are handled correctly.
391#
392for {set go 1; set i 1} {$go} {incr i} {
393 do_test malloc-9.$i {
394 sqlite_malloc_fail 0
395 catch {db close}
396 catch {file delete -force test.db}
397 catch {file delete -force test.db-journal}
398 catch {file delete -force test2.db}
399 catch {file delete -force test2.db-journal}
400
401 sqlite3 db test.db
402 execsql {
403 ATTACH 'test2.db' as test2;
404 CREATE TABLE abc1(a, b, c);
405 CREATE TABLE test2.abc2(a, b, c);
406 }
407
408 sqlite_malloc_fail $i
409 set v [catch {execsql {
410 BEGIN;
411 INSERT INTO abc1 VALUES(1, 2, 3);
412 INSERT INTO abc2 VALUES(1, 2, 3);
413 COMMIT;
414 }} msg]
415 set leftover [lindex [sqlite_malloc_stat] 2]
416 if {$leftover>0} {
417 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
418 set ::go 0
419 set v {1 1}
420 } else {
421 set v2 [expr {$msg=="" || $msg=="out of memory"}]
422 if {!$v2} {puts "\nError message returned: $msg"}
423 lappend v $v2
424 }
425 } {1 1}
426}
427
428
danielk197796fb0dd2004-06-30 09:49:22 +0000429# Ensure that no file descriptors were leaked.
danielk1977b5402fb2005-01-12 07:15:04 +0000430do_test malloc-99.X {
danielk197796fb0dd2004-06-30 09:49:22 +0000431 catch {db close}
432 set sqlite_open_file_count
433} {0}
434
drhed7c8552001-04-11 14:29:21 +0000435sqlite_malloc_fail 0
436finish_test