blob: ad501d42de2e43f6968054fb9e3663382ebe774c [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#
danielk19774397de52005-01-12 12:44:03 +000017# $Id: malloc.test,v 1.16 2005/01/12 12:44:04 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
danielk19774397de52005-01-12 12:44:03 +000030# Usage: do_malloc_test <test number> <options...>
31#
32# The first argument, <test number>, is an integer used to name the
33# tests executed by this proc. Options are as follows:
34#
35# -tclprep TCL script to run to prepare test.
36# -sqlprep SQL script to run to prepare test.
37# -tclbody TCL script to run with IO error simulation.
38# -sqlbody TCL script to run with IO error simulation.
39#
40proc do_malloc_test {tn args} {
41 array set ::mallocopts $args
42
43 set ::go 1
44 for {set ::n 1} {$::go} {incr ::n} {
45
46 do_test malloc-$tn.$::n {
47
48 sqlite_malloc_fail 0
49 catch {db close}
50 catch {file delete -force test.db}
51 catch {file delete -force test.db-journal}
52 catch {file delete -force test2.db}
53 catch {file delete -force test2.db-journal}
54 set ::DB [sqlite3 db test.db]
55
56 if {[info exists ::mallocopts(-tclprep)]} {
57 eval $::mallocopts(-tclprep)
58 }
59 if {[info exists ::mallocopts(-sqlprep)]} {
60 execsql $::mallocopts(-sqlprep)
61 }
62
63 sqlite_malloc_fail $::n
64 set ::mallocbody {}
65 if {[info exists ::mallocopts(-tclbody)]} {
66 append ::mallocbody "$::mallocopts(-tclbody)\n"
67 }
68 if {[info exists ::mallocopts(-sqlbody)]} {
69 append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
70 }
71
72 set v [catch $::mallocbody msg]
73
74 set leftover [lindex [sqlite_malloc_stat] 2]
75 if {$leftover>0} {
76 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
77 set ::go 0
78 set v {1 1}
79 } else {
80 set v2 [expr {$msg=="" || $msg=="out of memory"}]
81 if {!$v2} {puts "\nError message returned: $msg"}
82 lappend v $v2
83 }
84 } {1 1}
85 }
86}
87
88if 0 {
89
drhed7c8552001-04-11 14:29:21 +000090for {set go 1; set i 1} {$go} {incr i} {
91 do_test malloc-1.$i {
92 sqlite_malloc_fail 0
drh6d4abfb2001-10-22 02:58:08 +000093 catch {db close}
94 catch {file delete -force test.db}
95 catch {file delete -force test.db-journal}
drh46934232004-11-20 19:18:00 +000096 sqlite_malloc_fail $i [expr {$i%4}]
drhef4ac8f2004-06-19 00:16:31 +000097 set v [catch {sqlite3 db test.db} msg]
drh6d4abfb2001-10-22 02:58:08 +000098 if {$v} {
99 set msg ""
100 } else {
101 set v [catch {execsql {
102 CREATE TABLE t1(
103 a int, b float, c double, d text, e varchar(20),
104 primary key(a,b,c)
105 );
106 CREATE INDEX i1 ON t1(a,b);
107 INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there');
108 INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
109 SELECT * FROM t1;
110 SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
111 DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
112 SELECT count(*) FROM t1;
113 }} msg]
114 }
115 set leftover [lindex [sqlite_malloc_stat] 2]
116 if {$leftover>0} {
117 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
drhed7c8552001-04-11 14:29:21 +0000118 set ::go 0
119 set v {1 1}
120 } else {
drh6d4abfb2001-10-22 02:58:08 +0000121 set v2 [expr {$msg=="" || $msg=="out of memory"}]
122 if {!$v2} {puts "\nError message returned: $msg"}
123 lappend v $v2
drhed7c8552001-04-11 14:29:21 +0000124 }
125 } {1 1}
126}
drhd4007282001-04-12 23:21:58 +0000127
danielk1977b5548a82004-06-26 13:51:33 +0000128# Ensure that no file descriptors were leaked.
129do_test malloc-1.X {
130 catch {db close}
131 set sqlite_open_file_count
132} {0}
133
drhd4007282001-04-12 23:21:58 +0000134set fd [open ./data.tmp w]
drh6d4abfb2001-10-22 02:58:08 +0000135for {set i 1} {$i<=20} {incr i} {
drh5f3b4ab2004-05-27 17:22:54 +0000136 puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}] abcdefghijklmnopqrstuvwxyz"
drhd4007282001-04-12 23:21:58 +0000137}
138close $fd
139
140for {set go 1; set i 1} {$go} {incr i} {
141 do_test malloc-2.$i {
142 sqlite_malloc_fail 0
drh6d4abfb2001-10-22 02:58:08 +0000143 catch {db close}
144 catch {file delete -force test.db}
145 catch {file delete -force test.db-journal}
drhd4007282001-04-12 23:21:58 +0000146 sqlite_malloc_fail $i
drhef4ac8f2004-06-19 00:16:31 +0000147 set v [catch {sqlite3 db test.db} msg]
drh6d4abfb2001-10-22 02:58:08 +0000148 if {$v} {
149 set msg ""
150 } else {
151 set v [catch {execsql {
152 CREATE TABLE t1(a int, b int, c int);
153 CREATE INDEX i1 ON t1(a,b);
drh5f3b4ab2004-05-27 17:22:54 +0000154 INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz');
155 INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz');
156 INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz');
157 INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz');
158 INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz');
159 INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz');
drh6d4abfb2001-10-22 02:58:08 +0000160 SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
161 UPDATE t1 SET b=b||b||b||b;
162 UPDATE t1 SET b=a WHERE a in (10,12,22);
163 INSERT INTO t1(c,b,a) VALUES(20,10,5);
164 INSERT INTO t1 SELECT * FROM t1
165 WHERE a IN (SELECT a FROM t1 WHERE a<10);
166 DELETE FROM t1 WHERE a>=10;
167 DROP INDEX i1;
168 DELETE FROM t1;
169 }} msg]
170 }
171 set leftover [lindex [sqlite_malloc_stat] 2]
172 if {$leftover>0} {
173 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
drhd4007282001-04-12 23:21:58 +0000174 set ::go 0
175 set v {1 1}
176 } else {
drh6d4abfb2001-10-22 02:58:08 +0000177 set v2 [expr {$msg=="" || $msg=="out of memory"}]
178 if {!$v2} {puts "\nError message returned: $msg"}
179 lappend v $v2
180 }
181 } {1 1}
182}
183
danielk1977b5548a82004-06-26 13:51:33 +0000184# Ensure that no file descriptors were leaked.
185do_test malloc-2.X {
186 catch {db close}
187 set sqlite_open_file_count
188} {0}
189
drh6d4abfb2001-10-22 02:58:08 +0000190for {set go 1; set i 1} {$go} {incr i} {
191 do_test malloc-3.$i {
192 sqlite_malloc_fail 0
193 catch {db close}
194 catch {file delete -force test.db}
195 catch {file delete -force test.db-journal}
196 sqlite_malloc_fail $i
drhef4ac8f2004-06-19 00:16:31 +0000197 set v [catch {sqlite3 db test.db} msg]
drh6d4abfb2001-10-22 02:58:08 +0000198 if {$v} {
199 set msg ""
200 } else {
201 set v [catch {execsql {
202 BEGIN TRANSACTION;
203 CREATE TABLE t1(a int, b int, c int);
204 CREATE INDEX i1 ON t1(a,b);
drh5f3b4ab2004-05-27 17:22:54 +0000205 INSERT INTO t1 VALUES(1,1,99);
206 INSERT INTO t1 VALUES(2,4,98);
207 INSERT INTO t1 VALUES(3,9,97);
208 INSERT INTO t1 VALUES(4,16,96);
209 INSERT INTO t1 VALUES(5,25,95);
210 INSERT INTO t1 VALUES(6,36,94);
drh6d4abfb2001-10-22 02:58:08 +0000211 INSERT INTO t1(c,b,a) VALUES(20,10,5);
212 DELETE FROM t1 WHERE a>=10;
213 DROP INDEX i1;
214 DELETE FROM t1;
215 ROLLBACK;
216 }} msg]
217 }
218 set leftover [lindex [sqlite_malloc_stat] 2]
219 if {$leftover>0} {
220 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
221 set ::go 0
222 set v {1 1}
223 } else {
224 set v2 [expr {$msg=="" || $msg=="out of memory"}]
225 if {!$v2} {puts "\nError message returned: $msg"}
226 lappend v $v2
227 }
228 } {1 1}
229}
danielk1977b5548a82004-06-26 13:51:33 +0000230
231# Ensure that no file descriptors were leaked.
232do_test malloc-3.X {
233 catch {db close}
234 set sqlite_open_file_count
235} {0}
236
drh6d4abfb2001-10-22 02:58:08 +0000237for {set go 1; set i 1} {$go} {incr i} {
238 do_test malloc-4.$i {
239 sqlite_malloc_fail 0
240 catch {db close}
241 catch {file delete -force test.db}
242 catch {file delete -force test.db-journal}
243 sqlite_malloc_fail $i
drhef4ac8f2004-06-19 00:16:31 +0000244 set v [catch {sqlite3 db test.db} msg]
drh6d4abfb2001-10-22 02:58:08 +0000245 if {$v} {
246 set msg ""
247 } else {
248 set v [catch {execsql {
249 BEGIN TRANSACTION;
250 CREATE TABLE t1(a int, b int, c int);
251 CREATE INDEX i1 ON t1(a,b);
drh5f3b4ab2004-05-27 17:22:54 +0000252 INSERT INTO t1 VALUES(1,1,99);
253 INSERT INTO t1 VALUES(2,4,98);
254 INSERT INTO t1 VALUES(3,9,97);
255 INSERT INTO t1 VALUES(4,16,96);
256 INSERT INTO t1 VALUES(5,25,95);
257 INSERT INTO t1 VALUES(6,36,94);
drh6d4abfb2001-10-22 02:58:08 +0000258 UPDATE t1 SET b=a WHERE a in (10,12,22);
259 INSERT INTO t1 SELECT * FROM t1
260 WHERE a IN (SELECT a FROM t1 WHERE a<10);
261 DROP INDEX i1;
262 DELETE FROM t1;
263 COMMIT;
264 }} msg]
265 }
266 set leftover [lindex [sqlite_malloc_stat] 2]
267 if {$leftover>0} {
268 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
269 set ::go 0
270 set v {1 1}
271 } else {
272 set v2 [expr {$msg=="" || $msg=="out of memory"}]
273 if {!$v2} {puts "\nError message returned: $msg"}
274 lappend v $v2
drhd4007282001-04-12 23:21:58 +0000275 }
276 } {1 1}
277}
danielk1977b5548a82004-06-26 13:51:33 +0000278
279# Ensure that no file descriptors were leaked.
280do_test malloc-4.X {
281 catch {db close}
282 set sqlite_open_file_count
283} {0}
284
drhe4697f52002-05-23 02:09:03 +0000285for {set go 1; set i 1} {$go} {incr i} {
286 do_test malloc-5.$i {
287 sqlite_malloc_fail 0
288 catch {db close}
289 catch {file delete -force test.db}
290 catch {file delete -force test.db-journal}
291 sqlite_malloc_fail $i
drhef4ac8f2004-06-19 00:16:31 +0000292 set v [catch {sqlite3 db test.db} msg]
drhe4697f52002-05-23 02:09:03 +0000293 if {$v} {
294 set msg ""
295 } else {
296 set v [catch {execsql {
297 BEGIN TRANSACTION;
298 CREATE TABLE t1(a,b);
299 CREATE TABLE t2(x,y);
300 CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
301 INSERT INTO t2(x,y) VALUES(new.rowid,1);
302 END;
303 INSERT INTO t1(a,b) VALUES(2,3);
304 COMMIT;
305 }} msg]
306 }
307 set leftover [lindex [sqlite_malloc_stat] 2]
308 if {$leftover>0} {
309 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
310 set ::go 0
311 set v {1 1}
312 } else {
313 set v2 [expr {$msg=="" || $msg=="out of memory"}]
314 if {!$v2} {puts "\nError message returned: $msg"}
315 lappend v $v2
316 }
317 } {1 1}
318}
danielk1977b5548a82004-06-26 13:51:33 +0000319
320# Ensure that no file descriptors were leaked.
321do_test malloc-5.X {
322 catch {db close}
323 set sqlite_open_file_count
324} {0}
325
danielk197796fb0dd2004-06-30 09:49:22 +0000326for {set go 1; set i 1} {$go} {incr i} {
327 do_test malloc-6.$i {
328 sqlite_malloc_fail 0
329 catch {db close}
330 catch {file delete -force test.db}
331 catch {file delete -force test.db-journal}
332 sqlite3 db test.db
333 execsql {
334 BEGIN TRANSACTION;
335 CREATE TABLE t1(a);
336 INSERT INTO t1 VALUES(1);
337 INSERT INTO t1 SELECT a*2 FROM t1;
338 INSERT INTO t1 SELECT a*2 FROM t1;
339 INSERT INTO t1 SELECT a*2 FROM t1;
340 INSERT INTO t1 SELECT a*2 FROM t1;
341 INSERT INTO t1 SELECT a*2 FROM t1;
342 INSERT INTO t1 SELECT a*2 FROM t1;
343 INSERT INTO t1 SELECT a*2 FROM t1;
344 INSERT INTO t1 SELECT a*2 FROM t1;
345 INSERT INTO t1 SELECT a*2 FROM t1;
346 INSERT INTO t1 SELECT a*2 FROM t1;
347 DELETE FROM t1 where rowid%5 = 0;
348 COMMIT;
349 }
350 sqlite_malloc_fail $i
351 set v [catch {execsql {
352 VACUUM;
353 }} msg]
354 set leftover [lindex [sqlite_malloc_stat] 2]
355 if {$leftover>0} {
356 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
357 set ::go 0
358 set v {1 1}
359 } else {
360 set v2 [expr {$msg=="" || $msg=="out of memory"}]
361 if {!$v2} {puts "\nError message returned: $msg"}
362 lappend v $v2
363 }
364 } {1 1}
365}
366
danielk197701427a62005-01-11 13:02:33 +0000367for {set go 1; set i 1} {$go} {incr i} {
368 do_test malloc-7.$i {
369 sqlite_malloc_fail 0
370 catch {db close}
371 catch {file delete -force test.db}
372 catch {file delete -force test.db-journal}
373 sqlite3 db test.db
374 execsql {
375 CREATE TABLE t1(a, b);
376 INSERT INTO t1 VALUES(1, 2);
377 INSERT INTO t1 VALUES(3, 4);
378 INSERT INTO t1 VALUES(5, 6);
danielk1977b5402fb2005-01-12 07:15:04 +0000379 INSERT INTO t1 VALUES(7, randstr(1200,1200));
danielk197701427a62005-01-11 13:02:33 +0000380 }
381 sqlite_malloc_fail $i
382 set v [catch {execsql {
danielk1977b5402fb2005-01-12 07:15:04 +0000383 SELECT min(a) FROM t1 WHERE a<6 GROUP BY b;
384 SELECT a FROM t1 WHERE a<6 ORDER BY a;
385 SELECT b FROM t1 WHERE a>6;
danielk197701427a62005-01-11 13:02:33 +0000386 }} msg]
387 set leftover [lindex [sqlite_malloc_stat] 2]
388 if {$leftover>0} {
389 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
390 set ::go 0
391 set v {1 1}
392 } else {
393 set v2 [expr {$msg=="" || $msg=="out of memory"}]
394 if {!$v2} {puts "\nError message returned: $msg"}
395 lappend v $v2
396 }
397 } {1 1}
398}
399
danielk1977b5402fb2005-01-12 07:15:04 +0000400# This block is designed to test that some malloc failures that may
401# occur in vdbeapi.c. Specifically, if a malloc failure that occurs
402# when converting UTF-16 text to integers and real numbers is handled
403# correctly.
404#
danielk19778b60e0f2005-01-12 09:10:39 +0000405# This is done by retrieving a string from the database engine and
406# manipulating it using the sqlite3_column_*** APIs. This doesn't
407# actually return an error to the user when a malloc() fails.. That
408# could be viewed as a bug.
409#
410# These tests only run if UTF-16 support is compiled in.
danielk1977b5402fb2005-01-12 07:15:04 +0000411#
412for {set go 1; set i 1} {$go && $::sqlite_options(utf16)} {incr i} {
413 do_test malloc-8.$i {
414 sqlite_malloc_fail 0
415 catch {db close}
416 catch {file delete -force test.db}
417 catch {file delete -force test.db-journal}
418
419 set ::DB [sqlite3 db test.db]
420 set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?"
421 set ::STMT [sqlite3_prepare $::DB $sql -1 X]
422 sqlite3_step $::STMT
423
424 if { $::tcl_platform(byteOrder)=="littleEndian" } {
425 set ::bomstr "\xFF\xFE"
426 } else {
427 set ::bomstr "\xFE\xFF"
428 }
429 append ::bomstr [encoding convertto unicode "123456789_123456789_12345678"]
430
431 sqlite_malloc_fail $i
432 catch {
433 sqlite3_column_text16 $::STMT 0
434 sqlite3_column_int $::STMT 0
435 sqlite3_column_text16 $::STMT 1
436 sqlite3_column_double $::STMT 1
437 sqlite3_reset $::STMT
438 sqlite3_bind_text16 $::STMT 1 $::bomstr 60
439
440 } msg
441 sqlite3_finalize $::STMT
442 if {[lindex [sqlite_malloc_stat] 2]>0} {
443 set ::go 0
444 }
445 expr 0
446 } {0}
447}
448
danielk19774397de52005-01-12 12:44:03 +0000449
danielk19778b60e0f2005-01-12 09:10:39 +0000450# This block tests that malloc() failures that occur whilst commiting
451# a multi-file transaction are handled correctly.
452#
danielk19774397de52005-01-12 12:44:03 +0000453do_malloc_test 9 -sqlprep {
454 ATTACH 'test2.db' as test2;
455 CREATE TABLE abc1(a, b, c);
456 CREATE TABLE test2.abc2(a, b, c);
457} -sqlbody {
458 BEGIN;
459 INSERT INTO abc1 VALUES(1, 2, 3);
460 INSERT INTO abc2 VALUES(1, 2, 3);
461 COMMIT;
danielk19778b60e0f2005-01-12 09:10:39 +0000462}
463
danielk19774397de52005-01-12 12:44:03 +0000464}
465
466# This block tests malloc() failures that occur while opening a
467# connection to a database.
468do_malloc_test 10 -sqlprep {
469 CREATE TABLE abc(a, b, c);
470} -tclbody {
471 set ::DB [sqlite3 db2 test.db]
472 db2 eval {SELECT * FROM sqlite_master}
473 db2 close
474}
475
476# This block tests malloc() failures that occur within calls to
477# sqlite3_create_function().
478do_malloc_test 11 -tclbody {
479 if {[string match [sqlite3_create_function $::DB] SQLITE_NOMEM]==0} {
480 error "out of memory"
481 }
482}
483
484do_malloc_test 12 -tclbody {
485 set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"]
486 append sql16 "\00\00"
487 set ::STMT [sqlite3_prepare16 $::DB $sql16 -1 DUMMY]
488 sqlite3_finalize $::STMT
489}
danielk19778b60e0f2005-01-12 09:10:39 +0000490
danielk197796fb0dd2004-06-30 09:49:22 +0000491# Ensure that no file descriptors were leaked.
danielk1977b5402fb2005-01-12 07:15:04 +0000492do_test malloc-99.X {
danielk197796fb0dd2004-06-30 09:49:22 +0000493 catch {db close}
494 set sqlite_open_file_count
495} {0}
496
drhed7c8552001-04-11 14:29:21 +0000497sqlite_malloc_fail 0
498finish_test