3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
6 # 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.
10 #***********************************************************************
11 # This file attempts to check that the library can recover from a malloc()
12 # failure when sqlite3_global_recover() is invoked.
14 # $Id: malloc2.test,v 1.3 2005/06/06 14:45:43 drh Exp $
16 set testdir [file dirname $argv0]
17 source $testdir/tester.tcl
19 # Only run these tests if memory debugging is turned on.
21 if {[info command sqlite_malloc_stat]==""} {
22 puts "Skipping malloc tests: not compiled with -DSQLITE_DEBUG..."
27 ifcapable !globalrecover {
32 # Generate a checksum based on the contents of the database. If the
33 # checksum of two databases is the same, and the integrity-check passes
34 # for both, the two databases are identical.
40 SELECT name FROM sqlite_master WHERE type = 'table' UNION
41 SELECT name FROM sqlite_temp_master WHERE type = 'table' UNION
42 SELECT 'sqlite_master' UNION
43 SELECT 'sqlite_temp_master'
47 SELECT name FROM sqlite_master WHERE type = 'table' UNION
48 SELECT 'sqlite_master'
51 set tbllist [$db eval $sql]
53 foreach tbl $tbllist {
54 append txt [$db eval "SELECT * FROM $tbl"]
60 proc do_malloc2_test {tn args} {
61 array set ::mallocopts $args
64 for {set ::n 1} {true} {incr ::n} {
66 # Run the SQL. Malloc number $::n is set to fail. A malloc() failure
67 # may or may not be reported.
68 sqlite_malloc_fail $::n
69 do_test malloc2-$tn.$::n.2 {
70 set res [catchsql [string trim $::mallocopts(-sql)]]
72 0==[string compare $res {1 {out of memory}}] ||
81 # If $::n is greater than the number of malloc() calls required to
82 # execute the SQL, then this test is finished. Break out of the loop.
83 if {[lindex [sqlite_malloc_stat] 2]>0} {
88 # Nothing should work now, because the allocator should refuse to
89 # allocate any memory.
90 do_test malloc2-$tn.$::n.3 {
91 catchsql {SELECT 'nothing should work'}
94 # Recover from the malloc failure.
95 do_test malloc2-$tn.$::n.4 {
99 set ::DB [sqlite3 db test.db]
102 sqlite3_global_recover
106 # Checksum the database.
107 do_test malloc2-$tn.$::n.5 {
111 integrity_check malloc2-$tn.$::n.6
112 if {$::nErr>1} return
117 do_test malloc2.1.setup {
119 CREATE TABLE abc(a, b, c);
120 INSERT INTO abc VALUES(10, 20, 30);
121 INSERT INTO abc VALUES(40, 50, 60);
122 CREATE INDEX abc_i ON abc(a, b, c);
125 do_malloc2_test 1.1 -sql {
128 do_malloc2_test 1.2 -sql {
129 UPDATE abc SET c = c+10;
131 do_malloc2_test 1.3 -sql {
132 INSERT INTO abc VALUES(70, 80, 90);
134 do_malloc2_test 1.4 -sql {
137 do_test malloc2.1.5 {
143 do_test malloc2.2.setup {
145 CREATE TABLE def(a, b, c);
146 CREATE INDEX def_i1 ON def(a);
147 CREATE INDEX def_i2 ON def(c);
150 for {set i 0} {$i<20} {incr i} {
152 INSERT INTO def VALUES(randstr(300,300),randstr(300,300),randstr(300,300));
159 do_malloc2_test 2 -sql {
161 UPDATE def SET a = randstr(100,100) WHERE (oid%9)==0;
162 INSERT INTO def SELECT * FROM def WHERE (oid%13)==0;
164 CREATE INDEX def_i3 ON def(b);
166 UPDATE def SET a = randstr(100,100) WHERE (oid%9)==1;
167 INSERT INTO def SELECT * FROM def WHERE (oid%13)==1;
169 CREATE TABLE def2 AS SELECT * FROM def;
171 CREATE TABLE def AS SELECT * FROM def2;
174 DELETE FROM def WHERE (oid%9)==2;
175 INSERT INTO def SELECT * FROM def WHERE (oid%13)==2;
180 do_test malloc2.3.setup {
182 CREATE TEMP TABLE ghi(a, b, c);
185 for {set i 0} {$i<20} {incr i} {
187 INSERT INTO ghi VALUES(randstr(300,300),randstr(300,300),randstr(300,300));
194 do_malloc2_test 3 -sql {
196 CREATE INDEX ghi_i1 ON ghi(a);
197 UPDATE def SET a = randstr(100,100) WHERE (oid%2)==0;
198 UPDATE ghi SET a = randstr(100,100) WHERE (oid%2)==0;
203 ############################################################################
204 # The test cases below are to increase the code coverage in btree.c and
205 # pager.c of this test file. The idea is that each malloc() that occurs in
206 # these two source files should be made to fail at least once.
211 do_malloc2_test 4.1 -sql {
212 SELECT * FROM def ORDER BY oid ASC;
213 SELECT * FROM def ORDER BY oid DESC;
215 do_malloc2_test 4.2 -sql {
216 PRAGMA cache_size = 10;
219 -- This will put about 25 pages on the free list.
220 DELETE FROM def WHERE 1;
222 -- Allocate 32 new root pages. This will exercise the 'extract specific
223 -- page from the freelist' code when in auto-vacuum mode (see the
224 -- allocatePage() routine in btree.c).
225 CREATE TABLE t1(a UNIQUE, b UNIQUE, c UNIQUE);
226 CREATE TABLE t2(a UNIQUE, b UNIQUE, c UNIQUE);
227 CREATE TABLE t3(a UNIQUE, b UNIQUE, c UNIQUE);
228 CREATE TABLE t4(a UNIQUE, b UNIQUE, c UNIQUE);
229 CREATE TABLE t5(a UNIQUE, b UNIQUE, c UNIQUE);
230 CREATE TABLE t6(a UNIQUE, b UNIQUE, c UNIQUE);
231 CREATE TABLE t7(a UNIQUE, b UNIQUE, c UNIQUE);
232 CREATE TABLE t8(a UNIQUE, b UNIQUE, c UNIQUE);
237 ########################################################################
238 # Test that the global linked list of database handles works. An assert()
239 # will fail if there is some problem.
247 # Close the head of the list:
250 # Close the end of the list:
253 # Close a handle from the middle of the list:
256 # Close the other two. Then open and close one more database, to make
257 # sure the head of the list was set back to NULL.
264 ########################################################################
265 # Check that if a statement is active sqlite3_global_recover doesn't reset
266 # the sqlite3_malloc_failed variable.
267 do_test malloc2-6.1 {
268 set ::STMT [sqlite3_prepare $::DB {SELECT * FROM def} -1 DUMMY]
271 do_test malloc2-6.2 {
273 sqlite_malloc_fail 100
277 } {1 {out of memory}}
278 do_test malloc2-6.3 {
279 sqlite3_global_recover
281 do_test malloc2-6.4 {
285 } {1 {out of memory}}
286 do_test malloc2-6.5 {
287 sqlite3_reset $::STMT
289 do_test malloc2-6.6 {
290 sqlite3_global_recover
292 do_test malloc2-6.7 {
297 do_test malloc2-6.8 {
300 do_test malloc2-6.9 {
301 sqlite3_finalize $::STMT
303 do_test malloc2-6.10 {
307 ########################################################################
308 # Check that if an in-memory database is being used it is not possible
309 # to recover from a malloc() failure.
311 do_test malloc2-7.1 {
315 do_test malloc2-7.2 {
316 sqlite_malloc_fail 100
320 } {1 {out of memory}}
321 do_test malloc2-7.3 {
322 sqlite3_global_recover
324 do_test malloc2-7.4 {
328 } {1 {out of memory}}
329 do_test malloc2-7.5 {
332 do_test malloc2-7.6 {
333 sqlite3_global_recover
335 do_test malloc2-7.7 {