Better check for 64-bit.
[AROS-Contrib.git] / sqlite3 / test / malloc2.test
blob51164872a0f1b164dca15da2b7969e9b24175f1c
1 # 2005 March 18
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..."
23   finish_test
24   return
27 ifcapable !globalrecover {
28   finish_test
29   return
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.
36 proc cksum {db} {
37   set ret [list]
38   ifcapable tempdb {
39     set sql {
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'
44     }
45   } else {
46     set sql {
47       SELECT name FROM sqlite_master WHERE type = 'table' UNION
48       SELECT 'sqlite_master'
49     }
50   }
51   set tbllist [$db eval $sql]
52   set txt {}
53   foreach tbl $tbllist {
54     append txt [$db eval "SELECT * FROM $tbl"]
55   }
56   # puts txt=$txt
57   return [md5 $txt]
60 proc do_malloc2_test {tn args} {
61   array set ::mallocopts $args
62   set sum [cksum db]
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)]]
71       set rc [expr { 
72         0==[string compare $res {1 {out of memory}}] ||
73         0==[lindex $res 0]
74       }]
75       if {$rc!=1} {
76         puts "Error: $res"
77       }
78       set rc
79     } {1}
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} {
84       sqlite_malloc_fail -1
85       break
86     }
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'}
92     } {1 {out of memory}}
94     # Recover from the malloc failure.
95     do_test malloc2-$tn.$::n.4 {
96       if 0 {
97         db close
98         sqlite_malloc_fail -1
99         set ::DB [sqlite3 db test.db]
100         set dummy SQLITE_OK
101       } else {
102         sqlite3_global_recover
103       }
104     } {SQLITE_OK}
106     # Checksum the database.
107     do_test malloc2-$tn.$::n.5 {
108       cksum db
109     } $sum
111     integrity_check malloc2-$tn.$::n.6
112   if {$::nErr>1} return
113   }
114   unset ::mallocopts
117 do_test malloc2.1.setup {
118   execsql {
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);
123   }
124 } {}
125 do_malloc2_test 1.1 -sql {
126   SELECT * FROM abc;
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 {
135   DELETE FROM abc;
137 do_test malloc2.1.5 {
138   execsql {
139     SELECT * FROM abc;
140   }
141 } {}
143 do_test malloc2.2.setup {
144   execsql {
145     CREATE TABLE def(a, b, c);
146     CREATE INDEX def_i1 ON def(a);
147     CREATE INDEX def_i2 ON def(c);
148     BEGIN;
149   }
150   for {set i 0} {$i<20} {incr i} {
151     execsql {
152     INSERT INTO def VALUES(randstr(300,300),randstr(300,300),randstr(300,300));
153     }
154   }
155   execsql {
156     COMMIT;
157   }
158 } {}
159 do_malloc2_test 2 -sql {
160   BEGIN;
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;
170   DROP TABLE def;
171   CREATE TABLE def AS SELECT * FROM def2;
172   DROP TABLE def2;
174   DELETE FROM def WHERE (oid%9)==2;
175   INSERT INTO def SELECT * FROM def WHERE (oid%13)==2;
176   COMMIT;
179 ifcapable tempdb {
180   do_test malloc2.3.setup {
181     execsql {
182       CREATE TEMP TABLE ghi(a, b, c);
183       BEGIN;
184     }
185     for {set i 0} {$i<20} {incr i} {
186       execsql {
187       INSERT INTO ghi VALUES(randstr(300,300),randstr(300,300),randstr(300,300));
188       }
189     }
190     execsql {
191       COMMIT;
192     }
193   } {}
194   do_malloc2_test 3 -sql {
195     BEGIN;
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;
199     COMMIT;
200   }
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.
208 catchsql {
209   DROP TABLE ghi;
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;
217   BEGIN;
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);
234   ROLLBACK;
237 ########################################################################
238 # Test that the global linked list of database handles works. An assert()
239 # will fail if there is some problem.
240 do_test malloc2-5 {
241   sqlite3 db1 test.db
242   sqlite3 db2 test.db
243   sqlite3 db3 test.db
244   sqlite3 db4 test.db
245   sqlite3 db5 test.db
247   # Close the head of the list:
248   db5 close
249   
250   # Close the end of the list:
251   db1 close
253   # Close a handle from the middle of the list:
254   db3 close
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.
258   db2 close
259   db4 close
260   sqlite db1 test.db
261   db1 close
262 } {}
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]
269   sqlite3_step $::STMT
270 } {SQLITE_ROW}
271 do_test malloc2-6.2 {
272   sqlite3 db1 test.db
273   sqlite_malloc_fail 100
274   catchsql {
275     SELECT * FROM def;
276   } db1
277 } {1 {out of memory}}
278 do_test malloc2-6.3 {
279   sqlite3_global_recover
280 } {SQLITE_BUSY}
281 do_test malloc2-6.4 {
282   catchsql {
283     SELECT 'hello';
284   }
285 } {1 {out of memory}}
286 do_test malloc2-6.5 {
287   sqlite3_reset $::STMT
288 } {SQLITE_OK}
289 do_test malloc2-6.6 {
290   sqlite3_global_recover
291 } {SQLITE_OK}
292 do_test malloc2-6.7 {
293   catchsql {
294     SELECT 'hello';
295   }
296 } {0 hello}
297 do_test malloc2-6.8 {
298   sqlite3_step $::STMT
299 } {SQLITE_ERROR}
300 do_test malloc2-6.9 {
301   sqlite3_finalize $::STMT
302 } {SQLITE_SCHEMA}
303 do_test malloc2-6.10 {
304   db1 close
305 } {}
307 ########################################################################
308 # Check that if an in-memory database is being used it is not possible
309 # to recover from a malloc() failure.
310 ifcapable memorydb {
311   do_test malloc2-7.1 {
312     sqlite3 db1 :memory:
313     list
314   } {}
315   do_test malloc2-7.2 {
316     sqlite_malloc_fail 100
317     catchsql {
318       SELECT * FROM def;
319     } 
320   } {1 {out of memory}}
321   do_test malloc2-7.3 {
322     sqlite3_global_recover
323   } {SQLITE_ERROR}
324   do_test malloc2-7.4 {
325     catchsql {
326       SELECT 'hello';
327     }
328   } {1 {out of memory}}
329   do_test malloc2-7.5 {
330     db1 close
331   } {}
332   do_test malloc2-7.6 {
333     sqlite3_global_recover
334   } {SQLITE_OK}
335   do_test malloc2-7.7 {
336     catchsql {
337       SELECT 'hello';
338     }
339   } {0 hello}
342 finish_test