|
1 # 2001 September 15 |
|
2 # |
|
3 # Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved. |
|
4 # |
|
5 # The author disclaims copyright to this source code. In place of |
|
6 # a legal notice, here is a blessing: |
|
7 # |
|
8 # May you do good and not evil. |
|
9 # May you find forgiveness for yourself and forgive others. |
|
10 # May you share freely, never taking more than you give. |
|
11 # |
|
12 #*********************************************************************** |
|
13 # |
|
14 # This file attempts to check the behavior of the SQLite library in |
|
15 # an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, |
|
16 # the SQLite library accepts a special command (sqlite3_memdebug_fail N C) |
|
17 # which causes the N-th malloc to fail. This special feature is used |
|
18 # to see what happens in the library if a malloc were to really fail |
|
19 # due to an out-of-memory situation. |
|
20 # |
|
21 # $Id: malloc.test,v 1.67 2008/09/23 16:41:30 danielk1977 Exp $ |
|
22 |
|
23 set testdir [file dirname $argv0] |
|
24 source $testdir/tester.tcl |
|
25 |
|
26 |
|
27 # Only run these tests if memory debugging is turned on. |
|
28 # |
|
29 source $testdir/malloc_common.tcl |
|
30 if {!$MEMDEBUG} { |
|
31 puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." |
|
32 finish_test |
|
33 return |
|
34 } |
|
35 |
|
36 if {$tcl_platform(platform)!="symbian"} { |
|
37 # Do a couple of memory dumps just to exercise the memory dump logic |
|
38 # that that we can say that we have. |
|
39 # |
|
40 puts stderr "This is a test. Ignore the error that follows:" |
|
41 sqlite3_memdebug_dump $testdir |
|
42 puts "Memory dump to file memdump.txt..." |
|
43 sqlite3_memdebug_dump memdump.txt |
|
44 } |
|
45 |
|
46 ifcapable bloblit&&subquery { |
|
47 do_malloc_test 1 -tclprep { |
|
48 db close |
|
49 } -tclbody { |
|
50 if {[catch {sqlite3 db test.db}]} { |
|
51 error "out of memory" |
|
52 } |
|
53 sqlite3_extended_result_codes db 1 |
|
54 } -sqlbody { |
|
55 DROP TABLE IF EXISTS t1; |
|
56 CREATE TABLE t1( |
|
57 a int, b float, c double, d text, e varchar(20), |
|
58 primary key(a,b,c) |
|
59 ); |
|
60 CREATE INDEX i1 ON t1(a,b); |
|
61 INSERT INTO t1 VALUES(1,2.3,4.5,'hi',x'746865726500'); |
|
62 INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder'); |
|
63 SELECT * FROM t1; |
|
64 SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0; |
|
65 DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1); |
|
66 SELECT count(*), group_concat(e) FROM t1; |
|
67 SELECT b FROM t1 ORDER BY 1 COLLATE nocase; |
|
68 } |
|
69 } |
|
70 |
|
71 # Ensure that no file descriptors were leaked. |
|
72 do_test malloc-1.X { |
|
73 catch {db close} |
|
74 set sqlite_open_file_count |
|
75 } {0} |
|
76 |
|
77 ifcapable subquery { |
|
78 do_malloc_test 2 -sqlbody { |
|
79 CREATE TABLE t1(a int, b int default 'abc', c int default 1); |
|
80 CREATE INDEX i1 ON t1(a,b); |
|
81 INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz'); |
|
82 INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz'); |
|
83 INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz'); |
|
84 INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz'); |
|
85 INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz'); |
|
86 INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz'); |
|
87 SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1; |
|
88 UPDATE t1 SET b=b||b||b||b; |
|
89 UPDATE t1 SET b=a WHERE a in (10,12,22); |
|
90 INSERT INTO t1(c,b,a) VALUES(20,10,5); |
|
91 INSERT INTO t1 SELECT * FROM t1 |
|
92 WHERE a IN (SELECT a FROM t1 WHERE a<10); |
|
93 DELETE FROM t1 WHERE a>=10; |
|
94 DROP INDEX i1; |
|
95 DELETE FROM t1; |
|
96 } |
|
97 } |
|
98 |
|
99 # Ensure that no file descriptors were leaked. |
|
100 do_test malloc-2.X { |
|
101 catch {db close} |
|
102 set sqlite_open_file_count |
|
103 } {0} |
|
104 |
|
105 do_malloc_test 3 -sqlbody { |
|
106 BEGIN TRANSACTION; |
|
107 CREATE TABLE t1(a int, b int, c int); |
|
108 CREATE INDEX i1 ON t1(a,b); |
|
109 INSERT INTO t1 VALUES(1,1,99); |
|
110 INSERT INTO t1 VALUES(2,4,98); |
|
111 INSERT INTO t1 VALUES(3,9,97); |
|
112 INSERT INTO t1 VALUES(4,16,96); |
|
113 INSERT INTO t1 VALUES(5,25,95); |
|
114 INSERT INTO t1 VALUES(6,36,94); |
|
115 INSERT INTO t1(c,b,a) VALUES(20,10,5); |
|
116 DELETE FROM t1 WHERE a>=10; |
|
117 DROP INDEX i1; |
|
118 DELETE FROM t1; |
|
119 ROLLBACK; |
|
120 } |
|
121 |
|
122 |
|
123 # Ensure that no file descriptors were leaked. |
|
124 do_test malloc-3.X { |
|
125 catch {db close} |
|
126 set sqlite_open_file_count |
|
127 } {0} |
|
128 |
|
129 ifcapable subquery { |
|
130 do_malloc_test 4 -sqlbody { |
|
131 BEGIN TRANSACTION; |
|
132 CREATE TABLE t1(a int, b int, c int); |
|
133 CREATE INDEX i1 ON t1(a,b); |
|
134 INSERT INTO t1 VALUES(1,1,99); |
|
135 INSERT INTO t1 VALUES(2,4,98); |
|
136 INSERT INTO t1 VALUES(3,9,97); |
|
137 INSERT INTO t1 VALUES(4,16,96); |
|
138 INSERT INTO t1 VALUES(5,25,95); |
|
139 INSERT INTO t1 VALUES(6,36,94); |
|
140 UPDATE t1 SET b=a WHERE a in (10,12,22); |
|
141 INSERT INTO t1 SELECT * FROM t1 |
|
142 WHERE a IN (SELECT a FROM t1 WHERE a<10); |
|
143 DROP INDEX i1; |
|
144 DELETE FROM t1; |
|
145 COMMIT; |
|
146 } |
|
147 } |
|
148 |
|
149 # Ensure that no file descriptors were leaked. |
|
150 do_test malloc-4.X { |
|
151 catch {db close} |
|
152 set sqlite_open_file_count |
|
153 } {0} |
|
154 |
|
155 ifcapable trigger { |
|
156 do_malloc_test 5 -sqlbody { |
|
157 BEGIN TRANSACTION; |
|
158 CREATE TABLE t1(a,b); |
|
159 CREATE TABLE t2(x,y); |
|
160 CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.a = 2 BEGIN |
|
161 INSERT INTO t2(x,y) VALUES(new.rowid,1); |
|
162 INSERT INTO t2(x,y) SELECT * FROM t2; |
|
163 INSERT INTO t2 SELECT * FROM t2; |
|
164 UPDATE t2 SET y=y+1 WHERE x=new.rowid; |
|
165 SELECT 123; |
|
166 DELETE FROM t2 WHERE x=new.rowid; |
|
167 END; |
|
168 INSERT INTO t1(a,b) VALUES(2,3); |
|
169 COMMIT; |
|
170 } |
|
171 } |
|
172 |
|
173 # Ensure that no file descriptors were leaked. |
|
174 do_test malloc-5.X { |
|
175 catch {db close} |
|
176 set sqlite_open_file_count |
|
177 } {0} |
|
178 |
|
179 ifcapable vacuum { |
|
180 do_malloc_test 6 -sqlprep { |
|
181 BEGIN TRANSACTION; |
|
182 CREATE TABLE t1(a); |
|
183 INSERT INTO t1 VALUES(1); |
|
184 INSERT INTO t1 SELECT a*2 FROM t1; |
|
185 INSERT INTO t1 SELECT a*2 FROM t1; |
|
186 INSERT INTO t1 SELECT a*2 FROM t1; |
|
187 INSERT INTO t1 SELECT a*2 FROM t1; |
|
188 INSERT INTO t1 SELECT a*2 FROM t1; |
|
189 INSERT INTO t1 SELECT a*2 FROM t1; |
|
190 INSERT INTO t1 SELECT a*2 FROM t1; |
|
191 INSERT INTO t1 SELECT a*2 FROM t1; |
|
192 INSERT INTO t1 SELECT a*2 FROM t1; |
|
193 INSERT INTO t1 SELECT a*2 FROM t1; |
|
194 DELETE FROM t1 where rowid%5 = 0; |
|
195 COMMIT; |
|
196 } -sqlbody { |
|
197 VACUUM; |
|
198 } |
|
199 } |
|
200 |
|
201 do_malloc_test 7 -sqlprep { |
|
202 CREATE TABLE t1(a, b); |
|
203 INSERT INTO t1 VALUES(1, 2); |
|
204 INSERT INTO t1 VALUES(3, 4); |
|
205 INSERT INTO t1 VALUES(5, 6); |
|
206 INSERT INTO t1 VALUES(7, randstr(1200,1200)); |
|
207 } -sqlbody { |
|
208 SELECT min(a) FROM t1 WHERE a<6 GROUP BY b; |
|
209 SELECT a FROM t1 WHERE a<6 ORDER BY a; |
|
210 SELECT b FROM t1 WHERE a>6; |
|
211 } |
|
212 |
|
213 # This block is designed to test that some malloc failures that may |
|
214 # occur in vdbeapi.c. Specifically, if a malloc failure that occurs |
|
215 # when converting UTF-16 text to integers and real numbers is handled |
|
216 # correctly. |
|
217 # |
|
218 # This is done by retrieving a string from the database engine and |
|
219 # manipulating it using the sqlite3_column_*** APIs. This doesn't |
|
220 # actually return an error to the user when a malloc() fails.. That |
|
221 # could be viewed as a bug. |
|
222 # |
|
223 # These tests only run if UTF-16 support is compiled in. |
|
224 # |
|
225 ifcapable utf16 { |
|
226 set ::STMT {} |
|
227 do_malloc_test 8 -tclprep { |
|
228 set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?" |
|
229 set ::STMT [sqlite3_prepare db $sql -1 X] |
|
230 sqlite3_step $::STMT |
|
231 if { $::tcl_platform(byteOrder)=="littleEndian" } { |
|
232 set ::bomstr "\xFF\xFE" |
|
233 } else { |
|
234 set ::bomstr "\xFE\xFF" |
|
235 } |
|
236 append ::bomstr [encoding convertto unicode "123456789_123456789_12345678"] |
|
237 } -tclbody { |
|
238 sqlite3_column_text16 $::STMT 0 |
|
239 sqlite3_column_int $::STMT 0 |
|
240 sqlite3_column_text16 $::STMT 1 |
|
241 sqlite3_column_double $::STMT 1 |
|
242 set rc [sqlite3_reset $::STMT] |
|
243 if {$rc eq "SQLITE_NOMEM"} {error "out of memory"} |
|
244 sqlite3_bind_text16 $::STMT 1 $::bomstr 60 |
|
245 #catch {sqlite3_finalize $::STMT} |
|
246 #if {[lindex [sqlite_malloc_stat] 2]<=0} { |
|
247 # error "out of memory" |
|
248 #} |
|
249 } -cleanup { |
|
250 if {$::STMT!=""} { |
|
251 sqlite3_finalize $::STMT |
|
252 set ::STMT {} |
|
253 } |
|
254 } |
|
255 } |
|
256 |
|
257 # This block tests that malloc() failures that occur whilst commiting |
|
258 # a multi-file transaction are handled correctly. |
|
259 # |
|
260 do_malloc_test 9 -sqlprep { |
|
261 ATTACH 'test2.db' as test2; |
|
262 CREATE TABLE abc1(a, b, c); |
|
263 CREATE TABLE test2.abc2(a, b, c); |
|
264 } -sqlbody { |
|
265 BEGIN; |
|
266 INSERT INTO abc1 VALUES(1, 2, 3); |
|
267 INSERT INTO abc2 VALUES(1, 2, 3); |
|
268 COMMIT; |
|
269 } |
|
270 |
|
271 # This block tests malloc() failures that occur while opening a |
|
272 # connection to a database. |
|
273 do_malloc_test 10 -tclprep { |
|
274 catch {db2 close} |
|
275 db close |
|
276 file delete -force test.db test.db-journal |
|
277 sqlite3 db test.db |
|
278 sqlite3_extended_result_codes db 1 |
|
279 db eval {CREATE TABLE abc(a, b, c)} |
|
280 } -tclbody { |
|
281 db close |
|
282 sqlite3 db2 test.db |
|
283 sqlite3_extended_result_codes db2 1 |
|
284 db2 eval {SELECT * FROM sqlite_master} |
|
285 db2 close |
|
286 } |
|
287 |
|
288 # This block tests malloc() failures that occur within calls to |
|
289 # sqlite3_create_function(). |
|
290 do_malloc_test 11 -tclbody { |
|
291 set rc [sqlite3_create_function db] |
|
292 if {[string match $rc SQLITE_OK]} { |
|
293 set rc [sqlite3_create_aggregate db] |
|
294 } |
|
295 if {[string match $rc SQLITE_NOMEM]} { |
|
296 error "out of memory" |
|
297 } |
|
298 } |
|
299 |
|
300 do_malloc_test 12 -tclbody { |
|
301 set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"] |
|
302 append sql16 "\00\00" |
|
303 set ::STMT [sqlite3_prepare16 db $sql16 -1 DUMMY] |
|
304 sqlite3_finalize $::STMT |
|
305 } |
|
306 |
|
307 # Test malloc errors when replaying two hot journals from a 2-file |
|
308 # transaction. |
|
309 ifcapable crashtest&&attach { |
|
310 do_malloc_test 13 -tclprep { |
|
311 set rc [crashsql -delay 1 -file test2.db { |
|
312 ATTACH 'test2.db' as aux; |
|
313 PRAGMA cache_size = 10; |
|
314 BEGIN; |
|
315 CREATE TABLE aux.t2(a, b, c); |
|
316 CREATE TABLE t1(a, b, c); |
|
317 COMMIT; |
|
318 }] |
|
319 if {$rc!="1 {child process exited abnormally}"} { |
|
320 error "Wrong error message: $rc" |
|
321 } |
|
322 } -tclbody { |
|
323 db eval {ATTACH 'test2.db' as aux;} |
|
324 set rc [catch {db eval { |
|
325 SELECT * FROM t1; |
|
326 SELECT * FROM t2; |
|
327 }} err] |
|
328 if {$rc && $err!="no such table: t1"} { |
|
329 error $err |
|
330 } |
|
331 } |
|
332 } |
|
333 |
|
334 if {$tcl_platform(platform)!="windows" && $tcl_platform(platform)!="symbian"} { |
|
335 do_malloc_test 14 -tclprep { |
|
336 catch {db close} |
|
337 sqlite3 db2 test2.db |
|
338 sqlite3_extended_result_codes db2 1 |
|
339 db2 eval { |
|
340 PRAGMA synchronous = 0; |
|
341 CREATE TABLE t1(a, b); |
|
342 INSERT INTO t1 VALUES(1, 2); |
|
343 BEGIN; |
|
344 INSERT INTO t1 VALUES(3, 4); |
|
345 } |
|
346 copy_file test2.db test.db |
|
347 copy_file test2.db-journal test.db-journal |
|
348 db2 close |
|
349 } -tclbody { |
|
350 sqlite3 db test.db |
|
351 sqlite3_extended_result_codes db 1 |
|
352 |
|
353 # If an out-of-memory occurs within a call to a VFS layer function during |
|
354 # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit |
|
355 # [5668] for details. |
|
356 set rc [catch {db eval { SELECT * FROM t1 }} msg] |
|
357 if {$msg eq "database disk image is malformed"} { set msg "out of memory" } |
|
358 if {$rc} { error $msg } |
|
359 set msg |
|
360 } |
|
361 } |
|
362 |
|
363 proc string_compare {a b} { |
|
364 return [string compare $a $b] |
|
365 } |
|
366 |
|
367 # Test for malloc() failures in sqlite3_create_collation() and |
|
368 # sqlite3_create_collation16(). |
|
369 # |
|
370 ifcapable utf16 { |
|
371 do_malloc_test 15 -start 4 -tclbody { |
|
372 db collate string_compare string_compare |
|
373 if {[catch {add_test_collate db 1 1 1} msg]} { |
|
374 if {$msg=="SQLITE_NOMEM"} {set msg "out of memory"} |
|
375 error $msg |
|
376 } |
|
377 |
|
378 db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;} |
|
379 db complete {-- Useful comment} |
|
380 |
|
381 execsql { |
|
382 CREATE TABLE t1(a, b COLLATE string_compare); |
|
383 INSERT INTO t1 VALUES(10, 'string'); |
|
384 INSERT INTO t1 VALUES(10, 'string2'); |
|
385 } |
|
386 } |
|
387 } |
|
388 |
|
389 # Also test sqlite3_complete(). There are (currently) no malloc() |
|
390 # calls in this function, but test anyway against future changes. |
|
391 # |
|
392 do_malloc_test 16 -tclbody { |
|
393 db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;} |
|
394 db complete {-- Useful comment} |
|
395 db eval { |
|
396 SELECT * FROM sqlite_master; |
|
397 } |
|
398 } |
|
399 |
|
400 # Test handling of malloc() failures in sqlite3_open16(). |
|
401 # |
|
402 ifcapable utf16 { |
|
403 do_malloc_test 17 -tclbody { |
|
404 set DB2 0 |
|
405 set STMT 0 |
|
406 |
|
407 # open database using sqlite3_open16() |
|
408 set filename [encoding convertto unicode test.db] |
|
409 append filename "\x00\x00" |
|
410 set DB2 [sqlite3_open16 $filename -unused] |
|
411 if {0==$DB2} { |
|
412 error "out of memory" |
|
413 } |
|
414 sqlite3_extended_result_codes $DB2 1 |
|
415 |
|
416 # Prepare statement |
|
417 set rc [catch {sqlite3_prepare $DB2 {SELECT * FROM sqlite_master} -1 X} msg] |
|
418 if {[sqlite3_errcode $DB2] eq "SQLITE_IOERR+12"} { |
|
419 error "out of memory" |
|
420 } |
|
421 if {[regexp ".*automatic extension loading.*" [sqlite3_errmsg $DB2]]} { |
|
422 error "out of memory" |
|
423 } |
|
424 if {$rc} { |
|
425 error [string range $msg 4 end] |
|
426 } |
|
427 set STMT $msg |
|
428 |
|
429 # Finalize statement |
|
430 set rc [sqlite3_finalize $STMT] |
|
431 if {$rc!="SQLITE_OK"} { |
|
432 error [sqlite3_errmsg $DB2] |
|
433 } |
|
434 set STMT 0 |
|
435 |
|
436 # Close database |
|
437 set rc [sqlite3_close $DB2] |
|
438 if {$rc!="SQLITE_OK"} { |
|
439 error [sqlite3_errmsg $DB2] |
|
440 } |
|
441 set DB2 0 |
|
442 } -cleanup { |
|
443 if {$STMT!="0"} { |
|
444 sqlite3_finalize $STMT |
|
445 } |
|
446 if {$DB2!="0"} { |
|
447 set rc [sqlite3_close $DB2] |
|
448 } |
|
449 } |
|
450 } |
|
451 |
|
452 # Test handling of malloc() failures in sqlite3_errmsg16(). |
|
453 # |
|
454 ifcapable utf16 { |
|
455 do_malloc_test 18 -tclprep { |
|
456 catch { |
|
457 db eval "SELECT [string repeat longcolumnname 10] FROM sqlite_master" |
|
458 } |
|
459 } -tclbody { |
|
460 set utf16 [sqlite3_errmsg16 [sqlite3_connection_pointer db]] |
|
461 binary scan $utf16 c* bytes |
|
462 if {[llength $bytes]==0} { |
|
463 error "out of memory" |
|
464 } |
|
465 } |
|
466 } |
|
467 |
|
468 # This test is aimed at coverage testing. Specificly, it is supposed to |
|
469 # cause a malloc() only used when converting between the two utf-16 |
|
470 # encodings to fail (i.e. little-endian->big-endian). It only actually |
|
471 # hits this malloc() on little-endian hosts. |
|
472 # |
|
473 set static_string "\x00h\x00e\x00l\x00l\x00o" |
|
474 for {set l 0} {$l<10} {incr l} { |
|
475 append static_string $static_string |
|
476 } |
|
477 append static_string "\x00\x00" |
|
478 do_malloc_test 19 -tclprep { |
|
479 execsql { |
|
480 PRAGMA encoding = "UTF16be"; |
|
481 CREATE TABLE abc(a, b, c); |
|
482 } |
|
483 } -tclbody { |
|
484 unset -nocomplain ::STMT |
|
485 set r [catch { |
|
486 set ::STMT [sqlite3_prepare db {SELECT ?} -1 DUMMY] |
|
487 sqlite3_bind_text16 -static $::STMT 1 $static_string 112 |
|
488 } msg] |
|
489 if {$r} {error [string range $msg 4 end]} |
|
490 set msg |
|
491 } -cleanup { |
|
492 if {[info exists ::STMT]} { |
|
493 sqlite3_finalize $::STMT |
|
494 } |
|
495 } |
|
496 unset static_string |
|
497 |
|
498 # Make sure SQLITE_NOMEM is reported out on an ATTACH failure even |
|
499 # when the malloc failure occurs within the nested parse. |
|
500 # |
|
501 ifcapable attach { |
|
502 do_malloc_test 20 -tclprep { |
|
503 db close |
|
504 file delete -force test2.db test2.db-journal |
|
505 sqlite3 db test2.db |
|
506 sqlite3_extended_result_codes db 1 |
|
507 db eval {CREATE TABLE t1(x);} |
|
508 db close |
|
509 } -tclbody { |
|
510 if {[catch {sqlite3 db test.db}]} { |
|
511 error "out of memory" |
|
512 } |
|
513 sqlite3_extended_result_codes db 1 |
|
514 } -sqlbody { |
|
515 ATTACH DATABASE 'test2.db' AS t2; |
|
516 SELECT * FROM t1; |
|
517 DETACH DATABASE t2; |
|
518 } |
|
519 } |
|
520 |
|
521 # Test malloc failure whilst installing a foreign key. |
|
522 # |
|
523 ifcapable foreignkey { |
|
524 do_malloc_test 21 -sqlbody { |
|
525 CREATE TABLE abc(a, b, c, FOREIGN KEY(a) REFERENCES abc(b)) |
|
526 } |
|
527 } |
|
528 |
|
529 # Test malloc failure in an sqlite3_prepare_v2() call. |
|
530 # |
|
531 do_malloc_test 22 -tclbody { |
|
532 set ::STMT "" |
|
533 set r [catch { |
|
534 set ::STMT [ |
|
535 sqlite3_prepare_v2 db "SELECT * FROM sqlite_master" -1 DUMMY |
|
536 ] |
|
537 } msg] |
|
538 if {$r} {error [string range $msg 4 end]} |
|
539 } -cleanup { |
|
540 if {$::STMT ne ""} { |
|
541 sqlite3_finalize $::STMT |
|
542 set ::STMT "" |
|
543 } |
|
544 } |
|
545 |
|
546 ifcapable {pager_pragmas} { |
|
547 # This tests a special case - that an error that occurs while the pager |
|
548 # is trying to recover from error-state in exclusive-access mode works. |
|
549 # |
|
550 do_malloc_test 23 -tclprep { |
|
551 db eval { |
|
552 PRAGMA cache_size = 10; |
|
553 PRAGMA locking_mode = exclusive; |
|
554 BEGIN; |
|
555 CREATE TABLE abc(a, b, c); |
|
556 CREATE INDEX abc_i ON abc(a, b, c); |
|
557 INSERT INTO abc |
|
558 VALUES(randstr(100,100), randstr(100,100), randstr(100,100)); |
|
559 INSERT INTO abc |
|
560 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; |
|
561 INSERT INTO abc |
|
562 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; |
|
563 INSERT INTO abc |
|
564 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; |
|
565 INSERT INTO abc |
|
566 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; |
|
567 INSERT INTO abc |
|
568 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; |
|
569 COMMIT; |
|
570 } |
|
571 |
|
572 # This puts the pager into error state. |
|
573 # |
|
574 db eval BEGIN |
|
575 db eval {UPDATE abc SET a = 0 WHERE oid%2} |
|
576 set ::sqlite_io_error_pending 10 |
|
577 catch {db eval {ROLLBACK}} msg |
|
578 |
|
579 } -tclbody { |
|
580 # If an out-of-memory occurs within a call to a VFS layer function during |
|
581 # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit |
|
582 # [5668] for details. |
|
583 set rc [catch {db eval { SELECT * FROM abc LIMIT 10 }} msg] |
|
584 if {$msg eq "database disk image is malformed"} { set msg "out of memory" } |
|
585 if {$rc} { error $msg } |
|
586 set msg |
|
587 } -cleanup { |
|
588 set e [db eval {PRAGMA integrity_check}] |
|
589 if {$e ne "ok"} {error $e} |
|
590 } |
|
591 } |
|
592 |
|
593 ifcapable compound { |
|
594 do_malloc_test 24 -sqlprep { |
|
595 CREATE TABLE t1(a, b, c) |
|
596 } -sqlbody { |
|
597 SELECT 1 FROM t1 UNION SELECT 2 FROM t1 ORDER BY 1 |
|
598 } |
|
599 } |
|
600 |
|
601 ifcapable view&&trigger { |
|
602 do_malloc_test 25 -sqlprep { |
|
603 CREATE TABLE t1(a, b, c); |
|
604 CREATE VIEW v1 AS SELECT * FROM t1; |
|
605 CREATE TRIGGER v1t1 INSTEAD OF DELETE ON v1 BEGIN SELECT 1; END; |
|
606 CREATE TRIGGER v1t2 INSTEAD OF INSERT ON v1 BEGIN SELECT 1; END; |
|
607 CREATE TRIGGER v1t3 INSTEAD OF UPDATE ON v1 BEGIN SELECT 1; END; |
|
608 } -sqlbody { |
|
609 DELETE FROM v1 WHERE a = 1; |
|
610 INSERT INTO v1 VALUES(1, 2, 3); |
|
611 UPDATE v1 SET a = 1 WHERE b = 2; |
|
612 } |
|
613 } |
|
614 |
|
615 do_malloc_test 25 -sqlprep { |
|
616 CREATE TABLE abc(a, b, c); |
|
617 CREATE INDEX i1 ON abc(a, b); |
|
618 INSERT INTO abc VALUES(1, 2, 3); |
|
619 INSERT INTO abc VALUES(4, 5, 6); |
|
620 } -tclbody { |
|
621 # For each UPDATE executed, the cursor used for the SELECT statement |
|
622 # must be "saved". Because the cursor is open on an index, this requires |
|
623 # a malloc() to allocate space to save the index key. This test case is |
|
624 # aimed at testing the response of the library to a failure in that |
|
625 # particular malloc() call. |
|
626 db eval {SELECT a FROM abc ORDER BY a} { |
|
627 db eval {UPDATE abc SET b = b - 1 WHERE a = $a} |
|
628 } |
|
629 } |
|
630 |
|
631 # This test is designed to test a specific juncture in the sqlite code. |
|
632 # The database set up by -sqlprep script contains a single table B-Tree |
|
633 # of height 2. In the -tclbody script, the existing database connection |
|
634 # is closed and a new one opened and used to insert a new row into the |
|
635 # table B-Tree. By using a new connection, the outcome of a malloc() |
|
636 # failure while seeking to the right-hand side of the B-Tree to insert |
|
637 # a new record can be tested. |
|
638 # |
|
639 do_malloc_test 26 -sqlprep { |
|
640 BEGIN; |
|
641 CREATE TABLE t1(a, b); |
|
642 INSERT INTO t1 VALUES(1, randomblob(210)); |
|
643 INSERT INTO t1 VALUES(1, randomblob(210)); |
|
644 INSERT INTO t1 VALUES(1, randomblob(210)); |
|
645 INSERT INTO t1 VALUES(1, randomblob(210)); |
|
646 INSERT INTO t1 VALUES(1, randomblob(210)); |
|
647 COMMIT; |
|
648 } -tclbody { |
|
649 db close |
|
650 sqlite3 db test.db |
|
651 db eval { INSERT INTO t1 VALUES(1, randomblob(210)) } |
|
652 } |
|
653 |
|
654 # Test that no memory is leaked following a malloc() failure in |
|
655 # sqlite3_initialize(). |
|
656 # |
|
657 do_malloc_test 27 -tclprep { |
|
658 db close |
|
659 sqlite3_shutdown |
|
660 } -tclbody { |
|
661 set rc [sqlite3_initialize] |
|
662 if {$rc == "SQLITE_NOMEM"} { |
|
663 error "out of memory" |
|
664 } |
|
665 } |
|
666 |
|
667 # Ensure that no file descriptors were leaked. |
|
668 do_test malloc-99.X { |
|
669 catch {db close} |
|
670 set sqlite_open_file_count |
|
671 } {0} |
|
672 |
|
673 puts open-file-count=$sqlite_open_file_count |
|
674 finish_test |