persistentstorage/sqlite3api/TEST/TclScript/malloc.test
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     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