os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/malloc.test
changeset 0 bde4ae8d615e
     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