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