1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/malloc.test Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,674 @@
1.4 +# 2001 September 15
1.5 +#
1.6 +# Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
1.7 +#
1.8 +# The author disclaims copyright to this source code. In place of
1.9 +# a legal notice, here is a blessing:
1.10 +#
1.11 +# May you do good and not evil.
1.12 +# May you find forgiveness for yourself and forgive others.
1.13 +# May you share freely, never taking more than you give.
1.14 +#
1.15 +#***********************************************************************
1.16 +#
1.17 +# This file attempts to check the behavior of the SQLite library in
1.18 +# an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1,
1.19 +# the SQLite library accepts a special command (sqlite3_memdebug_fail N C)
1.20 +# which causes the N-th malloc to fail. This special feature is used
1.21 +# to see what happens in the library if a malloc were to really fail
1.22 +# due to an out-of-memory situation.
1.23 +#
1.24 +# $Id: malloc.test,v 1.67 2008/09/23 16:41:30 danielk1977 Exp $
1.25 +
1.26 +set testdir [file dirname $argv0]
1.27 +source $testdir/tester.tcl
1.28 +
1.29 +
1.30 +# Only run these tests if memory debugging is turned on.
1.31 +#
1.32 +source $testdir/malloc_common.tcl
1.33 +if {!$MEMDEBUG} {
1.34 + puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
1.35 + finish_test
1.36 + return
1.37 +}
1.38 +
1.39 +if {$tcl_platform(platform)!="symbian"} {
1.40 + # Do a couple of memory dumps just to exercise the memory dump logic
1.41 + # that that we can say that we have.
1.42 + #
1.43 + puts stderr "This is a test. Ignore the error that follows:"
1.44 + sqlite3_memdebug_dump $testdir
1.45 + puts "Memory dump to file memdump.txt..."
1.46 + sqlite3_memdebug_dump memdump.txt
1.47 +}
1.48 +
1.49 +ifcapable bloblit&&subquery {
1.50 + do_malloc_test 1 -tclprep {
1.51 + db close
1.52 + } -tclbody {
1.53 + if {[catch {sqlite3 db test.db}]} {
1.54 + error "out of memory"
1.55 + }
1.56 + sqlite3_extended_result_codes db 1
1.57 + } -sqlbody {
1.58 + DROP TABLE IF EXISTS t1;
1.59 + CREATE TABLE t1(
1.60 + a int, b float, c double, d text, e varchar(20),
1.61 + primary key(a,b,c)
1.62 + );
1.63 + CREATE INDEX i1 ON t1(a,b);
1.64 + INSERT INTO t1 VALUES(1,2.3,4.5,'hi',x'746865726500');
1.65 + INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
1.66 + SELECT * FROM t1;
1.67 + SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
1.68 + DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
1.69 + SELECT count(*), group_concat(e) FROM t1;
1.70 + SELECT b FROM t1 ORDER BY 1 COLLATE nocase;
1.71 + }
1.72 +}
1.73 +
1.74 +# Ensure that no file descriptors were leaked.
1.75 +do_test malloc-1.X {
1.76 + catch {db close}
1.77 + set sqlite_open_file_count
1.78 +} {0}
1.79 +
1.80 +ifcapable subquery {
1.81 + do_malloc_test 2 -sqlbody {
1.82 + CREATE TABLE t1(a int, b int default 'abc', c int default 1);
1.83 + CREATE INDEX i1 ON t1(a,b);
1.84 + INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz');
1.85 + INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz');
1.86 + INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz');
1.87 + INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz');
1.88 + INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz');
1.89 + INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz');
1.90 + SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
1.91 + UPDATE t1 SET b=b||b||b||b;
1.92 + UPDATE t1 SET b=a WHERE a in (10,12,22);
1.93 + INSERT INTO t1(c,b,a) VALUES(20,10,5);
1.94 + INSERT INTO t1 SELECT * FROM t1
1.95 + WHERE a IN (SELECT a FROM t1 WHERE a<10);
1.96 + DELETE FROM t1 WHERE a>=10;
1.97 + DROP INDEX i1;
1.98 + DELETE FROM t1;
1.99 + }
1.100 +}
1.101 +
1.102 +# Ensure that no file descriptors were leaked.
1.103 +do_test malloc-2.X {
1.104 + catch {db close}
1.105 + set sqlite_open_file_count
1.106 +} {0}
1.107 +
1.108 +do_malloc_test 3 -sqlbody {
1.109 + BEGIN TRANSACTION;
1.110 + CREATE TABLE t1(a int, b int, c int);
1.111 + CREATE INDEX i1 ON t1(a,b);
1.112 + INSERT INTO t1 VALUES(1,1,99);
1.113 + INSERT INTO t1 VALUES(2,4,98);
1.114 + INSERT INTO t1 VALUES(3,9,97);
1.115 + INSERT INTO t1 VALUES(4,16,96);
1.116 + INSERT INTO t1 VALUES(5,25,95);
1.117 + INSERT INTO t1 VALUES(6,36,94);
1.118 + INSERT INTO t1(c,b,a) VALUES(20,10,5);
1.119 + DELETE FROM t1 WHERE a>=10;
1.120 + DROP INDEX i1;
1.121 + DELETE FROM t1;
1.122 + ROLLBACK;
1.123 +}
1.124 +
1.125 +
1.126 +# Ensure that no file descriptors were leaked.
1.127 +do_test malloc-3.X {
1.128 + catch {db close}
1.129 + set sqlite_open_file_count
1.130 +} {0}
1.131 +
1.132 +ifcapable subquery {
1.133 + do_malloc_test 4 -sqlbody {
1.134 + BEGIN TRANSACTION;
1.135 + CREATE TABLE t1(a int, b int, c int);
1.136 + CREATE INDEX i1 ON t1(a,b);
1.137 + INSERT INTO t1 VALUES(1,1,99);
1.138 + INSERT INTO t1 VALUES(2,4,98);
1.139 + INSERT INTO t1 VALUES(3,9,97);
1.140 + INSERT INTO t1 VALUES(4,16,96);
1.141 + INSERT INTO t1 VALUES(5,25,95);
1.142 + INSERT INTO t1 VALUES(6,36,94);
1.143 + UPDATE t1 SET b=a WHERE a in (10,12,22);
1.144 + INSERT INTO t1 SELECT * FROM t1
1.145 + WHERE a IN (SELECT a FROM t1 WHERE a<10);
1.146 + DROP INDEX i1;
1.147 + DELETE FROM t1;
1.148 + COMMIT;
1.149 + }
1.150 +}
1.151 +
1.152 +# Ensure that no file descriptors were leaked.
1.153 +do_test malloc-4.X {
1.154 + catch {db close}
1.155 + set sqlite_open_file_count
1.156 +} {0}
1.157 +
1.158 +ifcapable trigger {
1.159 + do_malloc_test 5 -sqlbody {
1.160 + BEGIN TRANSACTION;
1.161 + CREATE TABLE t1(a,b);
1.162 + CREATE TABLE t2(x,y);
1.163 + CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.a = 2 BEGIN
1.164 + INSERT INTO t2(x,y) VALUES(new.rowid,1);
1.165 + INSERT INTO t2(x,y) SELECT * FROM t2;
1.166 + INSERT INTO t2 SELECT * FROM t2;
1.167 + UPDATE t2 SET y=y+1 WHERE x=new.rowid;
1.168 + SELECT 123;
1.169 + DELETE FROM t2 WHERE x=new.rowid;
1.170 + END;
1.171 + INSERT INTO t1(a,b) VALUES(2,3);
1.172 + COMMIT;
1.173 + }
1.174 +}
1.175 +
1.176 +# Ensure that no file descriptors were leaked.
1.177 +do_test malloc-5.X {
1.178 + catch {db close}
1.179 + set sqlite_open_file_count
1.180 +} {0}
1.181 +
1.182 +ifcapable vacuum {
1.183 + do_malloc_test 6 -sqlprep {
1.184 + BEGIN TRANSACTION;
1.185 + CREATE TABLE t1(a);
1.186 + INSERT INTO t1 VALUES(1);
1.187 + INSERT INTO t1 SELECT a*2 FROM t1;
1.188 + INSERT INTO t1 SELECT a*2 FROM t1;
1.189 + INSERT INTO t1 SELECT a*2 FROM t1;
1.190 + INSERT INTO t1 SELECT a*2 FROM t1;
1.191 + INSERT INTO t1 SELECT a*2 FROM t1;
1.192 + INSERT INTO t1 SELECT a*2 FROM t1;
1.193 + INSERT INTO t1 SELECT a*2 FROM t1;
1.194 + INSERT INTO t1 SELECT a*2 FROM t1;
1.195 + INSERT INTO t1 SELECT a*2 FROM t1;
1.196 + INSERT INTO t1 SELECT a*2 FROM t1;
1.197 + DELETE FROM t1 where rowid%5 = 0;
1.198 + COMMIT;
1.199 + } -sqlbody {
1.200 + VACUUM;
1.201 + }
1.202 +}
1.203 +
1.204 +do_malloc_test 7 -sqlprep {
1.205 + CREATE TABLE t1(a, b);
1.206 + INSERT INTO t1 VALUES(1, 2);
1.207 + INSERT INTO t1 VALUES(3, 4);
1.208 + INSERT INTO t1 VALUES(5, 6);
1.209 + INSERT INTO t1 VALUES(7, randstr(1200,1200));
1.210 +} -sqlbody {
1.211 + SELECT min(a) FROM t1 WHERE a<6 GROUP BY b;
1.212 + SELECT a FROM t1 WHERE a<6 ORDER BY a;
1.213 + SELECT b FROM t1 WHERE a>6;
1.214 +}
1.215 +
1.216 +# This block is designed to test that some malloc failures that may
1.217 +# occur in vdbeapi.c. Specifically, if a malloc failure that occurs
1.218 +# when converting UTF-16 text to integers and real numbers is handled
1.219 +# correctly.
1.220 +#
1.221 +# This is done by retrieving a string from the database engine and
1.222 +# manipulating it using the sqlite3_column_*** APIs. This doesn't
1.223 +# actually return an error to the user when a malloc() fails.. That
1.224 +# could be viewed as a bug.
1.225 +#
1.226 +# These tests only run if UTF-16 support is compiled in.
1.227 +#
1.228 +ifcapable utf16 {
1.229 + set ::STMT {}
1.230 + do_malloc_test 8 -tclprep {
1.231 + set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?"
1.232 + set ::STMT [sqlite3_prepare db $sql -1 X]
1.233 + sqlite3_step $::STMT
1.234 + if { $::tcl_platform(byteOrder)=="littleEndian" } {
1.235 + set ::bomstr "\xFF\xFE"
1.236 + } else {
1.237 + set ::bomstr "\xFE\xFF"
1.238 + }
1.239 + append ::bomstr [encoding convertto unicode "123456789_123456789_12345678"]
1.240 + } -tclbody {
1.241 + sqlite3_column_text16 $::STMT 0
1.242 + sqlite3_column_int $::STMT 0
1.243 + sqlite3_column_text16 $::STMT 1
1.244 + sqlite3_column_double $::STMT 1
1.245 + set rc [sqlite3_reset $::STMT]
1.246 + if {$rc eq "SQLITE_NOMEM"} {error "out of memory"}
1.247 + sqlite3_bind_text16 $::STMT 1 $::bomstr 60
1.248 + #catch {sqlite3_finalize $::STMT}
1.249 + #if {[lindex [sqlite_malloc_stat] 2]<=0} {
1.250 + # error "out of memory"
1.251 + #}
1.252 + } -cleanup {
1.253 + if {$::STMT!=""} {
1.254 + sqlite3_finalize $::STMT
1.255 + set ::STMT {}
1.256 + }
1.257 + }
1.258 +}
1.259 +
1.260 +# This block tests that malloc() failures that occur whilst commiting
1.261 +# a multi-file transaction are handled correctly.
1.262 +#
1.263 +do_malloc_test 9 -sqlprep {
1.264 + ATTACH 'test2.db' as test2;
1.265 + CREATE TABLE abc1(a, b, c);
1.266 + CREATE TABLE test2.abc2(a, b, c);
1.267 +} -sqlbody {
1.268 + BEGIN;
1.269 + INSERT INTO abc1 VALUES(1, 2, 3);
1.270 + INSERT INTO abc2 VALUES(1, 2, 3);
1.271 + COMMIT;
1.272 +}
1.273 +
1.274 +# This block tests malloc() failures that occur while opening a
1.275 +# connection to a database.
1.276 +do_malloc_test 10 -tclprep {
1.277 + catch {db2 close}
1.278 + db close
1.279 + file delete -force test.db test.db-journal
1.280 + sqlite3 db test.db
1.281 + sqlite3_extended_result_codes db 1
1.282 + db eval {CREATE TABLE abc(a, b, c)}
1.283 +} -tclbody {
1.284 + db close
1.285 + sqlite3 db2 test.db
1.286 + sqlite3_extended_result_codes db2 1
1.287 + db2 eval {SELECT * FROM sqlite_master}
1.288 + db2 close
1.289 +}
1.290 +
1.291 +# This block tests malloc() failures that occur within calls to
1.292 +# sqlite3_create_function().
1.293 +do_malloc_test 11 -tclbody {
1.294 + set rc [sqlite3_create_function db]
1.295 + if {[string match $rc SQLITE_OK]} {
1.296 + set rc [sqlite3_create_aggregate db]
1.297 + }
1.298 + if {[string match $rc SQLITE_NOMEM]} {
1.299 + error "out of memory"
1.300 + }
1.301 +}
1.302 +
1.303 +do_malloc_test 12 -tclbody {
1.304 + set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"]
1.305 + append sql16 "\00\00"
1.306 + set ::STMT [sqlite3_prepare16 db $sql16 -1 DUMMY]
1.307 + sqlite3_finalize $::STMT
1.308 +}
1.309 +
1.310 +# Test malloc errors when replaying two hot journals from a 2-file
1.311 +# transaction.
1.312 +ifcapable crashtest&&attach {
1.313 + do_malloc_test 13 -tclprep {
1.314 + set rc [crashsql -delay 1 -file test2.db {
1.315 + ATTACH 'test2.db' as aux;
1.316 + PRAGMA cache_size = 10;
1.317 + BEGIN;
1.318 + CREATE TABLE aux.t2(a, b, c);
1.319 + CREATE TABLE t1(a, b, c);
1.320 + COMMIT;
1.321 + }]
1.322 + if {$rc!="1 {child process exited abnormally}"} {
1.323 + error "Wrong error message: $rc"
1.324 + }
1.325 + } -tclbody {
1.326 + db eval {ATTACH 'test2.db' as aux;}
1.327 + set rc [catch {db eval {
1.328 + SELECT * FROM t1;
1.329 + SELECT * FROM t2;
1.330 + }} err]
1.331 + if {$rc && $err!="no such table: t1"} {
1.332 + error $err
1.333 + }
1.334 + }
1.335 +}
1.336 +
1.337 +if {$tcl_platform(platform)!="windows" && $tcl_platform(platform)!="symbian"} {
1.338 + do_malloc_test 14 -tclprep {
1.339 + catch {db close}
1.340 + sqlite3 db2 test2.db
1.341 + sqlite3_extended_result_codes db2 1
1.342 + db2 eval {
1.343 + PRAGMA synchronous = 0;
1.344 + CREATE TABLE t1(a, b);
1.345 + INSERT INTO t1 VALUES(1, 2);
1.346 + BEGIN;
1.347 + INSERT INTO t1 VALUES(3, 4);
1.348 + }
1.349 + copy_file test2.db test.db
1.350 + copy_file test2.db-journal test.db-journal
1.351 + db2 close
1.352 + } -tclbody {
1.353 + sqlite3 db test.db
1.354 + sqlite3_extended_result_codes db 1
1.355 +
1.356 + # If an out-of-memory occurs within a call to a VFS layer function during
1.357 + # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit
1.358 + # [5668] for details.
1.359 + set rc [catch {db eval { SELECT * FROM t1 }} msg]
1.360 + if {$msg eq "database disk image is malformed"} { set msg "out of memory" }
1.361 + if {$rc} { error $msg }
1.362 + set msg
1.363 + }
1.364 +}
1.365 +
1.366 +proc string_compare {a b} {
1.367 + return [string compare $a $b]
1.368 +}
1.369 +
1.370 +# Test for malloc() failures in sqlite3_create_collation() and
1.371 +# sqlite3_create_collation16().
1.372 +#
1.373 +ifcapable utf16 {
1.374 + do_malloc_test 15 -start 4 -tclbody {
1.375 + db collate string_compare string_compare
1.376 + if {[catch {add_test_collate db 1 1 1} msg]} {
1.377 + if {$msg=="SQLITE_NOMEM"} {set msg "out of memory"}
1.378 + error $msg
1.379 + }
1.380 +
1.381 + db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;}
1.382 + db complete {-- Useful comment}
1.383 +
1.384 + execsql {
1.385 + CREATE TABLE t1(a, b COLLATE string_compare);
1.386 + INSERT INTO t1 VALUES(10, 'string');
1.387 + INSERT INTO t1 VALUES(10, 'string2');
1.388 + }
1.389 + }
1.390 +}
1.391 +
1.392 +# Also test sqlite3_complete(). There are (currently) no malloc()
1.393 +# calls in this function, but test anyway against future changes.
1.394 +#
1.395 +do_malloc_test 16 -tclbody {
1.396 + db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;}
1.397 + db complete {-- Useful comment}
1.398 + db eval {
1.399 + SELECT * FROM sqlite_master;
1.400 + }
1.401 +}
1.402 +
1.403 +# Test handling of malloc() failures in sqlite3_open16().
1.404 +#
1.405 +ifcapable utf16 {
1.406 + do_malloc_test 17 -tclbody {
1.407 + set DB2 0
1.408 + set STMT 0
1.409 +
1.410 + # open database using sqlite3_open16()
1.411 + set filename [encoding convertto unicode test.db]
1.412 + append filename "\x00\x00"
1.413 + set DB2 [sqlite3_open16 $filename -unused]
1.414 + if {0==$DB2} {
1.415 + error "out of memory"
1.416 + }
1.417 + sqlite3_extended_result_codes $DB2 1
1.418 +
1.419 + # Prepare statement
1.420 + set rc [catch {sqlite3_prepare $DB2 {SELECT * FROM sqlite_master} -1 X} msg]
1.421 + if {[sqlite3_errcode $DB2] eq "SQLITE_IOERR+12"} {
1.422 + error "out of memory"
1.423 + }
1.424 + if {[regexp ".*automatic extension loading.*" [sqlite3_errmsg $DB2]]} {
1.425 + error "out of memory"
1.426 + }
1.427 + if {$rc} {
1.428 + error [string range $msg 4 end]
1.429 + }
1.430 + set STMT $msg
1.431 +
1.432 + # Finalize statement
1.433 + set rc [sqlite3_finalize $STMT]
1.434 + if {$rc!="SQLITE_OK"} {
1.435 + error [sqlite3_errmsg $DB2]
1.436 + }
1.437 + set STMT 0
1.438 +
1.439 + # Close database
1.440 + set rc [sqlite3_close $DB2]
1.441 + if {$rc!="SQLITE_OK"} {
1.442 + error [sqlite3_errmsg $DB2]
1.443 + }
1.444 + set DB2 0
1.445 + } -cleanup {
1.446 + if {$STMT!="0"} {
1.447 + sqlite3_finalize $STMT
1.448 + }
1.449 + if {$DB2!="0"} {
1.450 + set rc [sqlite3_close $DB2]
1.451 + }
1.452 + }
1.453 +}
1.454 +
1.455 +# Test handling of malloc() failures in sqlite3_errmsg16().
1.456 +#
1.457 +ifcapable utf16 {
1.458 + do_malloc_test 18 -tclprep {
1.459 + catch {
1.460 + db eval "SELECT [string repeat longcolumnname 10] FROM sqlite_master"
1.461 + }
1.462 + } -tclbody {
1.463 + set utf16 [sqlite3_errmsg16 [sqlite3_connection_pointer db]]
1.464 + binary scan $utf16 c* bytes
1.465 + if {[llength $bytes]==0} {
1.466 + error "out of memory"
1.467 + }
1.468 + }
1.469 +}
1.470 +
1.471 +# This test is aimed at coverage testing. Specificly, it is supposed to
1.472 +# cause a malloc() only used when converting between the two utf-16
1.473 +# encodings to fail (i.e. little-endian->big-endian). It only actually
1.474 +# hits this malloc() on little-endian hosts.
1.475 +#
1.476 +set static_string "\x00h\x00e\x00l\x00l\x00o"
1.477 +for {set l 0} {$l<10} {incr l} {
1.478 + append static_string $static_string
1.479 +}
1.480 +append static_string "\x00\x00"
1.481 +do_malloc_test 19 -tclprep {
1.482 + execsql {
1.483 + PRAGMA encoding = "UTF16be";
1.484 + CREATE TABLE abc(a, b, c);
1.485 + }
1.486 +} -tclbody {
1.487 + unset -nocomplain ::STMT
1.488 + set r [catch {
1.489 + set ::STMT [sqlite3_prepare db {SELECT ?} -1 DUMMY]
1.490 + sqlite3_bind_text16 -static $::STMT 1 $static_string 112
1.491 + } msg]
1.492 + if {$r} {error [string range $msg 4 end]}
1.493 + set msg
1.494 +} -cleanup {
1.495 + if {[info exists ::STMT]} {
1.496 + sqlite3_finalize $::STMT
1.497 + }
1.498 +}
1.499 +unset static_string
1.500 +
1.501 +# Make sure SQLITE_NOMEM is reported out on an ATTACH failure even
1.502 +# when the malloc failure occurs within the nested parse.
1.503 +#
1.504 +ifcapable attach {
1.505 + do_malloc_test 20 -tclprep {
1.506 + db close
1.507 + file delete -force test2.db test2.db-journal
1.508 + sqlite3 db test2.db
1.509 + sqlite3_extended_result_codes db 1
1.510 + db eval {CREATE TABLE t1(x);}
1.511 + db close
1.512 + } -tclbody {
1.513 + if {[catch {sqlite3 db test.db}]} {
1.514 + error "out of memory"
1.515 + }
1.516 + sqlite3_extended_result_codes db 1
1.517 + } -sqlbody {
1.518 + ATTACH DATABASE 'test2.db' AS t2;
1.519 + SELECT * FROM t1;
1.520 + DETACH DATABASE t2;
1.521 + }
1.522 +}
1.523 +
1.524 +# Test malloc failure whilst installing a foreign key.
1.525 +#
1.526 +ifcapable foreignkey {
1.527 + do_malloc_test 21 -sqlbody {
1.528 + CREATE TABLE abc(a, b, c, FOREIGN KEY(a) REFERENCES abc(b))
1.529 + }
1.530 +}
1.531 +
1.532 +# Test malloc failure in an sqlite3_prepare_v2() call.
1.533 +#
1.534 +do_malloc_test 22 -tclbody {
1.535 + set ::STMT ""
1.536 + set r [catch {
1.537 + set ::STMT [
1.538 + sqlite3_prepare_v2 db "SELECT * FROM sqlite_master" -1 DUMMY
1.539 + ]
1.540 + } msg]
1.541 + if {$r} {error [string range $msg 4 end]}
1.542 +} -cleanup {
1.543 + if {$::STMT ne ""} {
1.544 + sqlite3_finalize $::STMT
1.545 + set ::STMT ""
1.546 + }
1.547 +}
1.548 +
1.549 +ifcapable {pager_pragmas} {
1.550 + # This tests a special case - that an error that occurs while the pager
1.551 + # is trying to recover from error-state in exclusive-access mode works.
1.552 + #
1.553 + do_malloc_test 23 -tclprep {
1.554 + db eval {
1.555 + PRAGMA cache_size = 10;
1.556 + PRAGMA locking_mode = exclusive;
1.557 + BEGIN;
1.558 + CREATE TABLE abc(a, b, c);
1.559 + CREATE INDEX abc_i ON abc(a, b, c);
1.560 + INSERT INTO abc
1.561 + VALUES(randstr(100,100), randstr(100,100), randstr(100,100));
1.562 + INSERT INTO abc
1.563 + SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
1.564 + INSERT INTO abc
1.565 + SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
1.566 + INSERT INTO abc
1.567 + SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
1.568 + INSERT INTO abc
1.569 + SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
1.570 + INSERT INTO abc
1.571 + SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
1.572 + COMMIT;
1.573 + }
1.574 +
1.575 + # This puts the pager into error state.
1.576 + #
1.577 + db eval BEGIN
1.578 + db eval {UPDATE abc SET a = 0 WHERE oid%2}
1.579 + set ::sqlite_io_error_pending 10
1.580 + catch {db eval {ROLLBACK}} msg
1.581 +
1.582 + } -tclbody {
1.583 + # If an out-of-memory occurs within a call to a VFS layer function during
1.584 + # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit
1.585 + # [5668] for details.
1.586 + set rc [catch {db eval { SELECT * FROM abc LIMIT 10 }} msg]
1.587 + if {$msg eq "database disk image is malformed"} { set msg "out of memory" }
1.588 + if {$rc} { error $msg }
1.589 + set msg
1.590 + } -cleanup {
1.591 + set e [db eval {PRAGMA integrity_check}]
1.592 + if {$e ne "ok"} {error $e}
1.593 + }
1.594 +}
1.595 +
1.596 +ifcapable compound {
1.597 + do_malloc_test 24 -sqlprep {
1.598 + CREATE TABLE t1(a, b, c)
1.599 + } -sqlbody {
1.600 + SELECT 1 FROM t1 UNION SELECT 2 FROM t1 ORDER BY 1
1.601 + }
1.602 +}
1.603 +
1.604 +ifcapable view&&trigger {
1.605 + do_malloc_test 25 -sqlprep {
1.606 + CREATE TABLE t1(a, b, c);
1.607 + CREATE VIEW v1 AS SELECT * FROM t1;
1.608 + CREATE TRIGGER v1t1 INSTEAD OF DELETE ON v1 BEGIN SELECT 1; END;
1.609 + CREATE TRIGGER v1t2 INSTEAD OF INSERT ON v1 BEGIN SELECT 1; END;
1.610 + CREATE TRIGGER v1t3 INSTEAD OF UPDATE ON v1 BEGIN SELECT 1; END;
1.611 + } -sqlbody {
1.612 + DELETE FROM v1 WHERE a = 1;
1.613 + INSERT INTO v1 VALUES(1, 2, 3);
1.614 + UPDATE v1 SET a = 1 WHERE b = 2;
1.615 + }
1.616 +}
1.617 +
1.618 +do_malloc_test 25 -sqlprep {
1.619 + CREATE TABLE abc(a, b, c);
1.620 + CREATE INDEX i1 ON abc(a, b);
1.621 + INSERT INTO abc VALUES(1, 2, 3);
1.622 + INSERT INTO abc VALUES(4, 5, 6);
1.623 +} -tclbody {
1.624 + # For each UPDATE executed, the cursor used for the SELECT statement
1.625 + # must be "saved". Because the cursor is open on an index, this requires
1.626 + # a malloc() to allocate space to save the index key. This test case is
1.627 + # aimed at testing the response of the library to a failure in that
1.628 + # particular malloc() call.
1.629 + db eval {SELECT a FROM abc ORDER BY a} {
1.630 + db eval {UPDATE abc SET b = b - 1 WHERE a = $a}
1.631 + }
1.632 +}
1.633 +
1.634 +# This test is designed to test a specific juncture in the sqlite code.
1.635 +# The database set up by -sqlprep script contains a single table B-Tree
1.636 +# of height 2. In the -tclbody script, the existing database connection
1.637 +# is closed and a new one opened and used to insert a new row into the
1.638 +# table B-Tree. By using a new connection, the outcome of a malloc()
1.639 +# failure while seeking to the right-hand side of the B-Tree to insert
1.640 +# a new record can be tested.
1.641 +#
1.642 +do_malloc_test 26 -sqlprep {
1.643 + BEGIN;
1.644 + CREATE TABLE t1(a, b);
1.645 + INSERT INTO t1 VALUES(1, randomblob(210));
1.646 + INSERT INTO t1 VALUES(1, randomblob(210));
1.647 + INSERT INTO t1 VALUES(1, randomblob(210));
1.648 + INSERT INTO t1 VALUES(1, randomblob(210));
1.649 + INSERT INTO t1 VALUES(1, randomblob(210));
1.650 + COMMIT;
1.651 +} -tclbody {
1.652 + db close
1.653 + sqlite3 db test.db
1.654 + db eval { INSERT INTO t1 VALUES(1, randomblob(210)) }
1.655 +}
1.656 +
1.657 +# Test that no memory is leaked following a malloc() failure in
1.658 +# sqlite3_initialize().
1.659 +#
1.660 +do_malloc_test 27 -tclprep {
1.661 + db close
1.662 + sqlite3_shutdown
1.663 +} -tclbody {
1.664 + set rc [sqlite3_initialize]
1.665 + if {$rc == "SQLITE_NOMEM"} {
1.666 + error "out of memory"
1.667 + }
1.668 +}
1.669 +
1.670 +# Ensure that no file descriptors were leaked.
1.671 +do_test malloc-99.X {
1.672 + catch {db close}
1.673 + set sqlite_open_file_count
1.674 +} {0}
1.675 +
1.676 +puts open-file-count=$sqlite_open_file_count
1.677 +finish_test