File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / malloc.test
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 4 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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.1.1.1 2012/02/21 17:04:16 misho Exp $
   20: 
   21: set testdir [file dirname $argv0]
   22: source $testdir/tester.tcl
   23: 
   24: 
   25: # Only run these tests if memory debugging is turned on.
   26: #
   27: source $testdir/malloc_common.tcl
   28: if {!$MEMDEBUG} {
   29:    puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
   30:    finish_test
   31:    return
   32: }
   33: 
   34: # Do a couple of memory dumps just to exercise the memory dump logic
   35: # that that we can say that we have.
   36: #
   37: puts stderr "This is a test.  Ignore the error that follows:"
   38: sqlite3_memdebug_dump $testdir
   39: puts "Memory dump to file memdump.txt..."
   40: sqlite3_memdebug_dump memdump.txt
   41: 
   42: ifcapable bloblit&&subquery {
   43:   do_malloc_test 1 -tclprep {
   44:     db close
   45:   } -tclbody {
   46:     if {[catch {sqlite3 db test.db}]} {
   47:       error "out of memory"
   48:     }
   49:     sqlite3_extended_result_codes db 1
   50:   } -sqlbody {
   51:     DROP TABLE IF EXISTS t1;
   52:     CREATE TABLE t1(
   53:        a int, b float, c double, d text, e varchar(20),
   54:        primary key(a,b,c)
   55:     );
   56:     CREATE INDEX i1 ON t1(a,b);
   57:     INSERT INTO t1 VALUES(1,2.3,4.5,'hi',x'746865726500');
   58:     INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
   59:     SELECT * FROM t1;
   60:     SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
   61:     DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
   62:     SELECT count(*), group_concat(e) FROM t1;
   63:     SELECT b FROM t1 ORDER BY 1 COLLATE nocase;
   64:   } 
   65: }
   66: 
   67: # Ensure that no file descriptors were leaked.
   68: do_test malloc-1.X {
   69:   catch {db close}
   70:   set sqlite_open_file_count
   71: } {0}
   72: 
   73: ifcapable subquery {
   74:   do_malloc_test 2 -sqlbody {
   75:     CREATE TABLE t1(a int, b int default 'abc', c int default 1);
   76:     CREATE INDEX i1 ON t1(a,b);
   77:     INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz');
   78:     INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz');
   79:     INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz');
   80:     INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz');
   81:     INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz');
   82:     INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz');
   83:     SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
   84:     UPDATE t1 SET b=b||b||b||b;
   85:     UPDATE t1 SET b=a WHERE a in (10,12,22);
   86:     INSERT INTO t1(c,b,a) VALUES(20,10,5);
   87:     INSERT INTO t1 SELECT * FROM t1
   88:         WHERE a IN (SELECT a FROM t1 WHERE a<10);
   89:     DELETE FROM t1 WHERE a>=10;
   90:     DROP INDEX i1;
   91:     DELETE FROM t1;
   92:   } 
   93: }
   94: 
   95: # Ensure that no file descriptors were leaked.
   96: do_test malloc-2.X {
   97:   catch {db close}
   98:   set sqlite_open_file_count
   99: } {0}
  100: 
  101: do_malloc_test 3 -sqlbody {
  102:   BEGIN TRANSACTION;
  103:   CREATE TABLE t1(a int, b int, c int);
  104:   CREATE INDEX i1 ON t1(a,b);
  105:   INSERT INTO t1 VALUES(1,1,99);
  106:   INSERT INTO t1 VALUES(2,4,98);
  107:   INSERT INTO t1 VALUES(3,9,97);
  108:   INSERT INTO t1 VALUES(4,16,96);
  109:   INSERT INTO t1 VALUES(5,25,95);
  110:   INSERT INTO t1 VALUES(6,36,94);
  111:   INSERT INTO t1(c,b,a) VALUES(20,10,5);
  112:   DELETE FROM t1 WHERE a>=10;
  113:   DROP INDEX i1;
  114:   DELETE FROM t1;
  115:   ROLLBACK;
  116: } 
  117: 
  118: 
  119: # Ensure that no file descriptors were leaked.
  120: do_test malloc-3.X {
  121:   catch {db close}
  122:   set sqlite_open_file_count
  123: } {0}
  124: 
  125: ifcapable subquery {
  126:   do_malloc_test 4 -sqlbody {
  127:     BEGIN TRANSACTION;
  128:     CREATE TABLE t1(a int, b int, c int);
  129:     CREATE INDEX i1 ON t1(a,b);
  130:     INSERT INTO t1 VALUES(1,1,99);
  131:     INSERT INTO t1 VALUES(2,4,98);
  132:     INSERT INTO t1 VALUES(3,9,97);
  133:     INSERT INTO t1 VALUES(4,16,96);
  134:     INSERT INTO t1 VALUES(5,25,95);
  135:     INSERT INTO t1 VALUES(6,36,94);
  136:     UPDATE t1 SET b=a WHERE a in (10,12,22);
  137:     INSERT INTO t1 SELECT * FROM t1
  138:        WHERE a IN (SELECT a FROM t1 WHERE a<10);
  139:     DROP INDEX i1;
  140:     DELETE FROM t1;
  141:     COMMIT;
  142:   } 
  143: }
  144: 
  145: # Ensure that no file descriptors were leaked.
  146: do_test malloc-4.X {
  147:   catch {db close}
  148:   set sqlite_open_file_count
  149: } {0}
  150: 
  151: ifcapable trigger {
  152:   do_malloc_test 5 -sqlbody {
  153:     BEGIN TRANSACTION;
  154:     CREATE TABLE t1(a,b);
  155:     CREATE TABLE t2(x,y);
  156:     CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.a = 2 BEGIN
  157:       INSERT INTO t2(x,y) VALUES(new.rowid,1);
  158:       INSERT INTO t2(x,y) SELECT * FROM t2;
  159:       INSERT INTO t2 SELECT * FROM t2;
  160:       UPDATE t2 SET y=y+1 WHERE x=new.rowid;
  161:       SELECT 123;
  162:       DELETE FROM t2 WHERE x=new.rowid;
  163:     END;
  164:     INSERT INTO t1(a,b) VALUES(2,3);
  165:     COMMIT;
  166:   } 
  167: }
  168: 
  169: # Ensure that no file descriptors were leaked.
  170: do_test malloc-5.X {
  171:   catch {db close}
  172:   set sqlite_open_file_count
  173: } {0}
  174: 
  175: ifcapable vacuum {
  176:   do_malloc_test 6 -sqlprep {
  177:     BEGIN TRANSACTION;
  178:     CREATE TABLE t1(a);
  179:     INSERT INTO t1 VALUES(1);
  180:     INSERT INTO t1 SELECT a*2 FROM t1;
  181:     INSERT INTO t1 SELECT a*2 FROM t1;
  182:     INSERT INTO t1 SELECT a*2 FROM t1;
  183:     INSERT INTO t1 SELECT a*2 FROM t1;
  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:     DELETE FROM t1 where rowid%5 = 0;
  191:     COMMIT;
  192:   } -sqlbody {
  193:     VACUUM;
  194:   } 
  195: }
  196: 
  197: autoinstall_test_functions
  198: do_malloc_test 7 -sqlprep {
  199:   CREATE TABLE t1(a, b);
  200:   INSERT INTO t1 VALUES(1, 2);
  201:   INSERT INTO t1 VALUES(3, 4);
  202:   INSERT INTO t1 VALUES(5, 6);
  203:   INSERT INTO t1 VALUES(7, randstr(1200,1200));
  204: } -sqlbody {
  205:   SELECT min(a) FROM t1 WHERE a<6 GROUP BY b;
  206:   SELECT a FROM t1 WHERE a<6 ORDER BY a;
  207:   SELECT b FROM t1 WHERE a>6;
  208: }
  209: 
  210: # This block is designed to test that some malloc failures that may
  211: # occur in vdbeapi.c. Specifically, if a malloc failure that occurs
  212: # when converting UTF-16 text to integers and real numbers is handled
  213: # correctly. 
  214: #
  215: # This is done by retrieving a string from the database engine and
  216: # manipulating it using the sqlite3_column_*** APIs. This doesn't 
  217: # actually return an error to the user when a malloc() fails.. That 
  218: # could be viewed as a bug.
  219: #
  220: # These tests only run if UTF-16 support is compiled in.
  221: #
  222: ifcapable utf16 {
  223:   set ::STMT {}
  224:   do_malloc_test 8 -tclprep {
  225:     set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?"
  226:     set ::STMT [sqlite3_prepare db $sql -1 X]
  227:     sqlite3_step $::STMT
  228:     if { $::tcl_platform(byteOrder)=="littleEndian" } {
  229:       set ::bomstr "\xFF\xFE"
  230:     } else {
  231:       set ::bomstr "\xFE\xFF"
  232:     }
  233:     append ::bomstr [encoding convertto unicode "123456789_123456789_123456789"]
  234:   } -tclbody {
  235:     sqlite3_column_text16 $::STMT 0
  236:     sqlite3_column_int $::STMT 0
  237:     sqlite3_column_text16 $::STMT 1
  238:     sqlite3_column_double $::STMT 1
  239:     set rc [sqlite3_reset $::STMT]
  240:     if {$rc eq "SQLITE_NOMEM"} {error "out of memory"}
  241:     sqlite3_bind_text16 $::STMT 1 $::bomstr 60
  242:     #catch {sqlite3_finalize $::STMT}
  243:     #if {[lindex [sqlite_malloc_stat] 2]<=0} {
  244:     #  error "out of memory"
  245:     #}
  246:   } -cleanup {
  247:     if {$::STMT!=""} {
  248:       sqlite3_finalize $::STMT
  249:       set ::STMT {}
  250:     }
  251:   }
  252: }
  253: 
  254: # This block tests that malloc() failures that occur whilst commiting
  255: # a multi-file transaction are handled correctly.
  256: #
  257: do_malloc_test 9 -sqlprep {
  258:   ATTACH 'test2.db' as test2;
  259:   CREATE TABLE abc1(a, b, c);
  260:   CREATE TABLE test2.abc2(a, b, c);
  261: } -sqlbody {
  262:   BEGIN;
  263:   INSERT INTO abc1 VALUES(1, 2, 3);
  264:   INSERT INTO abc2 VALUES(1, 2, 3);
  265:   COMMIT;
  266: }
  267: 
  268: # This block tests malloc() failures that occur while opening a 
  269: # connection to a database.
  270: do_malloc_test 10 -tclprep {
  271:   catch {db2 close}
  272:   db close
  273:   forcedelete test.db test.db-journal
  274:   sqlite3 db test.db
  275:   sqlite3_extended_result_codes db 1
  276:   db eval {CREATE TABLE abc(a, b, c)}
  277: } -tclbody {
  278:   db close
  279:   sqlite3 db2 test.db
  280:   sqlite3_extended_result_codes db2 1
  281:   db2 eval {SELECT * FROM sqlite_master}
  282:   db2 close
  283: }
  284: 
  285: # This block tests malloc() failures that occur within calls to
  286: # sqlite3_create_function().
  287: do_malloc_test 11 -tclbody {
  288:   set rc [sqlite3_create_function db]
  289:   if {[string match $rc SQLITE_OK]} {
  290:     set rc [sqlite3_create_aggregate db]
  291:   }
  292:   if {[string match $rc SQLITE_NOMEM]} {
  293:     error "out of memory"
  294:   }
  295: }
  296: 
  297: do_malloc_test 12 -tclbody {
  298:   set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"]
  299:   append sql16 "\00\00"
  300:   set ::STMT [sqlite3_prepare16 db $sql16 -1 DUMMY]
  301:   sqlite3_finalize $::STMT
  302: }
  303: 
  304: # Test malloc errors when replaying two hot journals from a 2-file 
  305: # transaction.
  306: ifcapable crashtest&&attach {
  307:   do_malloc_test 13 -tclprep {
  308:     set rc [crashsql -delay 1 -file test2.db {
  309:       ATTACH 'test2.db' as aux;
  310:       PRAGMA cache_size = 10;
  311:       BEGIN;
  312:       CREATE TABLE aux.t2(a, b, c);
  313:       CREATE TABLE t1(a, b, c);
  314:       COMMIT;
  315:     }]
  316:     if {$rc!="1 {child process exited abnormally}"} {
  317:       error "Wrong error message: $rc"
  318:     }
  319:   } -tclbody {
  320:     db eval {ATTACH 'test2.db' as aux;}
  321:     set rc [catch {db eval {
  322:       SELECT * FROM t1; 
  323:       SELECT * FROM t2;
  324:     }} err]
  325:     if {$rc && $err!="no such table: t1"} {
  326:       error $err
  327:     }
  328:   }
  329: }
  330: 
  331: if {$tcl_platform(platform)!="windows"} {
  332:   do_malloc_test 14 -tclprep {
  333:     catch {db close}
  334:     sqlite3 db2 test2.db
  335:     sqlite3_extended_result_codes db2 1
  336:     db2 eval {
  337:       PRAGMA journal_mode = DELETE;    /* For inmemory_journal permutation */
  338:       PRAGMA synchronous = 0;
  339:       CREATE TABLE t1(a, b);
  340:       INSERT INTO t1 VALUES(1, 2);
  341:       BEGIN;
  342:       INSERT INTO t1 VALUES(3, 4);
  343:     }
  344:     forcecopy test2.db test.db
  345:     forcecopy test2.db-journal test.db-journal
  346:     db2 close
  347:   } -tclbody {
  348:     sqlite3 db test.db
  349:     sqlite3_extended_result_codes db 1
  350: 
  351:     # If an out-of-memory occurs within a call to a VFS layer function during
  352:     # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit
  353:     # [5668] for details.
  354:     set rc [catch {db eval { SELECT * FROM t1 }} msg]
  355:     if {$msg eq "database disk image is malformed"} { set msg "out of memory" }
  356:     if {$rc} { error $msg }
  357:     set msg
  358:   }
  359: }
  360: 
  361: proc string_compare {a b} {
  362:   return [string compare $a $b]
  363: }
  364: 
  365: # Test for malloc() failures in sqlite3_create_collation() and 
  366: # sqlite3_create_collation16().
  367: #
  368: ifcapable utf16 {
  369:   do_malloc_test 15 -start 4 -tclbody {
  370:     db collate string_compare string_compare
  371:     if {[catch {add_test_collate db 1 1 1} msg]} {
  372:       if {$msg=="SQLITE_NOMEM"} {set msg "out of memory"}
  373:       error $msg
  374:     }
  375:   
  376:     db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;}
  377:     db complete {-- Useful comment}
  378:   
  379:     execsql {
  380:       CREATE TABLE t1(a, b COLLATE string_compare);
  381:       INSERT INTO t1 VALUES(10, 'string');
  382:       INSERT INTO t1 VALUES(10, 'string2');
  383:     }
  384:   }
  385: }
  386: 
  387: # Also test sqlite3_complete(). There are (currently) no malloc()
  388: # calls in this function, but test anyway against future changes.
  389: #
  390: do_malloc_test 16 -tclbody {
  391:   db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;}
  392:   db complete {-- Useful comment}
  393:   db eval {
  394:     SELECT * FROM sqlite_master;
  395:   }
  396: }
  397: 
  398: # Test handling of malloc() failures in sqlite3_open16().
  399: #
  400: ifcapable utf16 {
  401:   do_malloc_test 17 -tclbody {
  402:     set DB2 0
  403:     set STMT 0
  404:   
  405:     # open database using sqlite3_open16()
  406:     set filename [encoding convertto unicode test.db]
  407:     append filename "\x00\x00"
  408:     set DB2 [sqlite3_open16 $filename -unused]
  409:     if {0==$DB2} {
  410:       error "out of memory"
  411:     }
  412:     sqlite3_extended_result_codes $DB2 1
  413:   
  414:     # Prepare statement
  415:     set rc [catch {sqlite3_prepare $DB2 {SELECT * FROM sqlite_master} -1 X} msg]
  416:     if {[sqlite3_errcode $DB2] eq "SQLITE_IOERR+12"} {
  417:       error "out of memory"
  418:     }
  419:     if {[regexp ".*automatic extension loading.*" [sqlite3_errmsg $DB2]]} {
  420:       error "out of memory"
  421:     }
  422:     if {$rc} {
  423:       error [string range $msg 4 end]
  424:     }
  425:     set STMT $msg
  426:   
  427:     # Finalize statement
  428:     set rc [sqlite3_finalize $STMT]
  429:     if {$rc!="SQLITE_OK"} {
  430:       error [sqlite3_errmsg $DB2]
  431:     }
  432:     set STMT 0
  433:   
  434:     # Close database
  435:     set rc [sqlite3_close $DB2]
  436:     if {$rc!="SQLITE_OK"} {
  437:       error [sqlite3_errmsg $DB2]
  438:     }
  439:     set DB2 0
  440:   } -cleanup {
  441:     if {$STMT!="0"} {
  442:       sqlite3_finalize $STMT
  443:     }
  444:     if {$DB2!="0"} {
  445:       set rc [sqlite3_close $DB2]
  446:     }
  447:   }
  448: }
  449: 
  450: # Test handling of malloc() failures in sqlite3_errmsg16().
  451: #
  452: ifcapable utf16 {
  453:   do_malloc_test 18 -tclprep {
  454:     catch {
  455:       db eval "SELECT [string repeat longcolumnname 10] FROM sqlite_master"
  456:     }
  457:   } -tclbody {
  458:     set utf16 [sqlite3_errmsg16 [sqlite3_connection_pointer db]]
  459:     binary scan $utf16 c* bytes
  460:     if {[llength $bytes]==0} {
  461:       error "out of memory"
  462:     }
  463:   }
  464: }
  465: 
  466: # This test is aimed at coverage testing. Specificly, it is supposed to
  467: # cause a malloc() only used when converting between the two utf-16 
  468: # encodings to fail (i.e. little-endian->big-endian). It only actually 
  469: # hits this malloc() on little-endian hosts.
  470: #
  471: set static_string "\x00h\x00e\x00l\x00l\x00o"
  472: for {set l 0} {$l<10} {incr l} {
  473:   append static_string $static_string
  474: }
  475: append static_string "\x00\x00"
  476: do_malloc_test 19 -tclprep {
  477:   execsql {
  478:     PRAGMA encoding = "UTF16be";
  479:     CREATE TABLE abc(a, b, c);
  480:   }
  481: } -tclbody {
  482:   unset -nocomplain ::STMT
  483:   set r [catch {
  484:     set ::STMT [sqlite3_prepare db {SELECT ?} -1 DUMMY]
  485:     sqlite3_bind_text16 -static $::STMT 1 $static_string 112
  486:   } msg]
  487:   if {$r} {error [string range $msg 4 end]}
  488:   set msg
  489: } -cleanup {
  490:   if {[info exists ::STMT]} {
  491:     sqlite3_finalize $::STMT
  492:   }
  493: }
  494: unset static_string
  495: 
  496: # Make sure SQLITE_NOMEM is reported out on an ATTACH failure even
  497: # when the malloc failure occurs within the nested parse.
  498: #
  499: ifcapable attach {
  500:   do_malloc_test 20 -tclprep {
  501:     db close
  502:     forcedelete test2.db test2.db-journal
  503:     sqlite3 db test2.db
  504:     sqlite3_extended_result_codes db 1
  505:     db eval {CREATE TABLE t1(x);}
  506:     db close
  507:   } -tclbody {
  508:     if {[catch {sqlite3 db test.db}]} {
  509:       error "out of memory"
  510:     }
  511:     sqlite3_extended_result_codes db 1
  512:   } -sqlbody {
  513:     ATTACH DATABASE 'test2.db' AS t2;
  514:     SELECT * FROM t1;
  515:     DETACH DATABASE t2;
  516:   } 
  517: }
  518: 
  519: # Test malloc failure whilst installing a foreign key.
  520: #
  521: ifcapable foreignkey {
  522:   do_malloc_test 21 -sqlbody {
  523:     CREATE TABLE abc(a, b, c, FOREIGN KEY(a) REFERENCES abc(b))
  524:   } 
  525: }
  526: 
  527: # Test malloc failure in an sqlite3_prepare_v2() call.
  528: #
  529: do_malloc_test 22 -tclbody {
  530:   set ::STMT ""
  531:   set r [catch {
  532:     set ::STMT [
  533:       sqlite3_prepare_v2 db "SELECT * FROM sqlite_master" -1 DUMMY
  534:     ]
  535:   } msg]
  536:   if {$r} {error [string range $msg 4 end]}
  537: } -cleanup {
  538:   if {$::STMT ne ""} {
  539:     sqlite3_finalize $::STMT
  540:     set ::STMT ""
  541:   }
  542: }
  543: 
  544: ifcapable {pager_pragmas} {
  545:   # This tests a special case - that an error that occurs while the pager
  546:   # is trying to recover from error-state in exclusive-access mode works.
  547:   #
  548:   do_malloc_test 23 -tclprep {
  549:     db eval {
  550:       PRAGMA cache_size = 10;
  551:       PRAGMA locking_mode = exclusive;
  552:       BEGIN;
  553:       CREATE TABLE abc(a, b, c);
  554:       CREATE INDEX abc_i ON abc(a, b, c);
  555:       INSERT INTO abc 
  556:         VALUES(randstr(100,100), randstr(100,100), randstr(100,100));
  557:       INSERT INTO abc 
  558:         SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
  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:       COMMIT;
  568:     }
  569:   
  570:     # This puts the pager into error state.
  571:     #
  572:     db eval BEGIN
  573:     db eval {UPDATE abc SET a = 0 WHERE oid%2}
  574:     set ::sqlite_io_error_pending 10
  575:     catch {db eval {ROLLBACK}} msg
  576: 
  577:   } -tclbody {
  578:     # If an out-of-memory occurs within a call to a VFS layer function during
  579:     # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit
  580:     # [5668] for details.
  581:     set rc [catch {db eval { SELECT * FROM abc LIMIT 10 }} msg]
  582:     if {$msg eq "database disk image is malformed"} { set msg "out of memory" }
  583:     if {$rc} { error $msg }
  584:     set msg
  585:   } -cleanup {
  586:     set e [db eval {PRAGMA integrity_check}]
  587:     if {$e ne "ok"} {error $e}
  588:   }
  589: }
  590: 
  591: ifcapable compound {
  592:   do_malloc_test 24 -sqlprep {
  593:     CREATE TABLE t1(a, b, c)
  594:   } -sqlbody {
  595:     SELECT 1 FROM t1 UNION SELECT 2 FROM t1 ORDER BY 1
  596:   }
  597: }
  598: 
  599: ifcapable view&&trigger {
  600:   do_malloc_test 25 -sqlprep {
  601:     CREATE TABLE t1(a, b, c);
  602:     CREATE VIEW v1 AS SELECT * FROM t1;
  603:     CREATE TRIGGER v1t1 INSTEAD OF DELETE ON v1 BEGIN SELECT 1; END;
  604:     CREATE TRIGGER v1t2 INSTEAD OF INSERT ON v1 BEGIN SELECT 1; END;
  605:     CREATE TRIGGER v1t3 INSTEAD OF UPDATE ON v1 BEGIN SELECT 1; END;
  606:   } -sqlbody {
  607:     DELETE FROM v1 WHERE a = 1;
  608:     INSERT INTO v1 VALUES(1, 2, 3);
  609:     UPDATE v1 SET a = 1 WHERE b = 2;
  610:   }
  611: }
  612: 
  613: do_malloc_test 25 -sqlprep {
  614:   CREATE TABLE abc(a, b, c);
  615:   CREATE INDEX i1 ON abc(a, b);
  616:   INSERT INTO abc VALUES(1, 2, 3);
  617:   INSERT INTO abc VALUES(4, 5, 6);
  618: } -tclbody {
  619:   # For each UPDATE executed, the cursor used for the SELECT statement
  620:   # must be "saved". Because the cursor is open on an index, this requires
  621:   # a malloc() to allocate space to save the index key. This test case is
  622:   # aimed at testing the response of the library to a failure in that
  623:   # particular malloc() call.
  624:   db eval {SELECT a FROM abc ORDER BY a} {
  625:     db eval {UPDATE abc SET b = b - 1 WHERE a = $a}
  626:   }
  627: }
  628: 
  629: # This test is designed to test a specific juncture in the sqlite code.
  630: # The database set up by -sqlprep script contains a single table B-Tree
  631: # of height 2. In the -tclbody script, the existing database connection
  632: # is closed and a new one opened and used to insert a new row into the
  633: # table B-Tree. By using a new connection, the outcome of a malloc() 
  634: # failure while seeking to the right-hand side of the B-Tree to insert 
  635: # a new record can be tested.
  636: #
  637: do_malloc_test 26 -sqlprep {
  638:   BEGIN;
  639:   CREATE TABLE t1(a, b);
  640:   INSERT INTO t1 VALUES(1, randomblob(210));
  641:   INSERT INTO t1 VALUES(1, randomblob(210));
  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:   COMMIT;
  646: } -tclbody {
  647:   db close
  648:   sqlite3 db test.db
  649:   db eval { INSERT INTO t1 VALUES(1, randomblob(210)) }
  650: }
  651: 
  652: # Test that no memory is leaked following a malloc() failure in
  653: # sqlite3_initialize().
  654: #
  655: do_malloc_test 27 -tclprep {
  656:   db close
  657:   sqlite3_shutdown
  658: } -tclbody {
  659:   set rc [sqlite3_initialize]
  660:   if {$rc == "SQLITE_NOMEM"} {
  661:     error "out of memory"
  662:   }
  663: }
  664: autoinstall_test_functions
  665: 
  666: # Test that malloc failures that occur while processing INDEXED BY
  667: # clauses are handled correctly.
  668: do_malloc_test 28 -sqlprep {
  669:   CREATE TABLE t1(a, b);
  670:   CREATE INDEX i1 ON t1(a);
  671:   CREATE VIEW v1 AS SELECT * FROM t1 INDEXED BY i1 WHERE a = 10;
  672: } -sqlbody {
  673:   SELECT * FROM t1 INDEXED BY i1 ORDER BY a;
  674:   SELECT * FROM v1;
  675: }
  676: 
  677: do_malloc_test 29 -sqlprep {
  678:   CREATE TABLE t1(a TEXT, b TEXT);
  679: } -sqlbody {
  680:   INSERT INTO t1 VALUES(1, -234);
  681:   INSERT INTO t1 SELECT * FROM t1 UNION ALL SELECT * FROM t1;
  682: }
  683: 
  684: do_malloc_test 30 -tclprep {
  685:   db eval {
  686:     CREATE TABLE t1(x PRIMARY KEY);
  687:     INSERT INTO t1 VALUES(randstr(500,500));
  688:     INSERT INTO t1 VALUES(randstr(500,500));
  689:     INSERT INTO t1 VALUES(randstr(500,500));
  690:   }
  691:   db close
  692:   sqlite3 db test.db
  693: 
  694:   # The DELETE command in the following block moves the overflow pages that
  695:   # are part of the primary key index to the free-list. But it does not
  696:   # actually load the content of the pages. This leads to the peculiar
  697:   # situation where cache entries exist, but are not populated with data.
  698:   # They are populated next time they are requested by the b-tree layer.
  699:   #
  700:   db eval {
  701:     BEGIN;
  702:       DELETE FROM t1;
  703:     ROLLBACK;
  704:   }
  705: } -sqlbody {
  706:   -- This statement requires the 'no-content' pages loaded by the DELETE
  707:   -- statement above. When requesting the pages, the content is loaded
  708:   -- from the database file. The point of this test case is to test handling
  709:   -- of malloc errors (including SQLITE_IOERR_NOMEM errors) when loading
  710:   -- the content.
  711:   SELECT * FROM t1 ORDER BY x;
  712: }
  713: 
  714: # After committing a transaction in persistent-journal mode, if a journal
  715: # size limit is configured SQLite may attempt to truncate the journal file.
  716: # This test verifies the libraries response to a malloc() failure during
  717: # this operation.
  718: #
  719: do_malloc_test 31 -sqlprep {
  720:   PRAGMA journal_mode = persist;
  721:   PRAGMA journal_size_limit = 1024;
  722:   CREATE TABLE t1(a PRIMARY KEY, b);
  723: } -sqlbody {
  724:   INSERT INTO t1 VALUES(1, 2);
  725: }
  726: 
  727: # When written, this test provoked an obscure change-counter bug.
  728: # 
  729: # If, when running in exclusive mode, a malloc() failure occurs
  730: # after the database file change-counter has been written but
  731: # before the transaction has been committed, then the transaction
  732: # is automatically rolled back. However, internally the 
  733: # Pager.changeCounterDone flag was being left set. This means
  734: # that if the same connection attempts another transaction following
  735: # the malloc failure and rollback, the change counter will not
  736: # be updated. This could corrupt another processes cache.
  737: #
  738: do_malloc_test 32 -tclprep {
  739:   # Build a small database containing an indexed table.
  740:   #
  741:   db eval {
  742:     PRAGMA locking_mode = normal;
  743:     BEGIN;
  744:     CREATE TABLE t1(a PRIMARY KEY, b);
  745:     INSERT INTO t1 VALUES(1, 'one');
  746:     INSERT INTO t1 VALUES(2, 'two');
  747:     INSERT INTO t1 VALUES(3, 'three');
  748:     COMMIT;
  749:     PRAGMA locking_mode = exclusive;
  750:   }
  751: 
  752:   # Open a second database connection. Load the table (but not index)
  753:   # into the second connections pager cache.
  754:   #
  755:   sqlite3 db2 test.db
  756:   db2 eval { 
  757:     PRAGMA locking_mode = normal;
  758:     SELECT b FROM t1;
  759:   }
  760: 
  761: } -tclbody {
  762:   # Running in exclusive mode, perform a database transaction that 
  763:   # modifies both the database table and index. For iterations where
  764:   # the malloc failure occurs after updating the change counter but
  765:   # before committing the transaction, this should result in the
  766:   # transaction being rolled back but the changeCounterDone flag
  767:   # left set.
  768:   #
  769:   db eval { UPDATE t1 SET a = a + 3 }
  770: } -cleanup {
  771: 
  772:   # Perform another transaction using the first connection. Unlock
  773:   # the database after doing so. If this is one of the right iterations,
  774:   # then this should result in the database contents being updated but
  775:   # the change-counter left as it is.
  776:   #
  777:   db eval { 
  778:     PRAGMA locking_mode = normal;
  779:     UPDATE t1 SET a = a + 3;
  780:   }
  781: 
  782:   # Now do an integrity check with the second connection. The second
  783:   # connection still has the database table in its cache. If this is
  784:   # one of the magic iterations and the change counter was not modified,
  785:   # then it won't realize that the cached data is out of date. Since
  786:   # the cached data won't match the up to date index data read from
  787:   # the database file, the integrity check should fail.
  788:   #
  789:   set zRepeat "transient"
  790:   if {$::iRepeat} {set zRepeat "persistent"}
  791:   do_test malloc-32.$zRepeat.${::n}.integrity {
  792:     execsql {PRAGMA integrity_check} db2
  793:   } {ok}
  794:   db2 close
  795: }
  796: 
  797: # The following two OOM tests verify that OOM handling works in the
  798: # code used to optimize "SELECT count(*) FROM <tbl>".
  799: #
  800: do_malloc_test 33 -tclprep {
  801:   db eval { PRAGMA cache_size = 10 }
  802:   db transaction {
  803:     db eval { CREATE TABLE abc(a, b) }
  804:     for {set i 0} {$i<500} {incr i} {
  805:       db eval {INSERT INTO abc VALUES(randstr(100,100), randstr(1000,1000))}
  806:     }
  807:   }
  808: } -sqlbody {
  809:   SELECT count(*) FROM abc;
  810: }
  811: do_malloc_test 34 -tclprep {
  812:   db eval { PRAGMA cache_size = 10 }
  813:   db transaction {
  814:     db eval { CREATE TABLE abc(a PRIMARY KEY, b) }
  815:     for {set i 0} {$i<500} {incr i} {
  816:       db eval {INSERT INTO abc VALUES(randstr(100,100), randstr(1000,1000))}
  817:     }
  818:   }
  819: } -sqlbody {
  820:   SELECT count(*) FROM abc;
  821: }
  822: 
  823: proc f {args} { error "Quite a long error!" }
  824: do_malloc_test 35 -tclprep {
  825:   db func f f
  826:   set ::STMT [sqlite3_prepare db "SELECT f()" -1 DUMMY]
  827:   sqlite3_step $::STMT
  828: } -tclbody {
  829:   sqlite3_finalize $::STMT
  830: } -cleanup {
  831:   # At one point an assert( !db->mallocFailed ) could fail in the following
  832:   # call to sqlite3_errmsg(). Because sqlite3_finalize() had failed to clear
  833:   # the flag before returning.
  834:   sqlite3_errmsg16 db
  835: }
  836: 
  837: do_malloc_test 36 -sqlprep {
  838:   CREATE TABLE t1(a, b);
  839:   INSERT INTO t1 VALUES(1, 2);
  840:   INSERT INTO t1 VALUES(3, 4);
  841: } -sqlbody {
  842:   SELECT test_agg_errmsg16(), group_concat(a) FROM t1
  843: }
  844: 
  845: # At one point, if an OOM occured immediately after obtaining a shared lock
  846: # on the database file, the file remained locked. This test case ensures
  847: # that bug has been fixed.i
  848: if {[db eval {PRAGMA locking_mode}]!="exclusive"} {
  849:   do_malloc_test 37 -tclprep {
  850:     sqlite3 db2 test.db
  851:     execsql {
  852:       CREATE TABLE t1(a, b);
  853:       INSERT INTO t1 VALUES(1, 2);
  854:     } db2
  855:   } -sqlbody {
  856:     SELECT * FROM t1;
  857:   } -cleanup {
  858:     # Try to write to the database using connection [db2]. If connection [db]
  859:     # has correctly released the shared lock, this write attempt should 
  860:     # succeed. If [db] has not released the lock, this should hit an 
  861:     # SQLITE_BUSY error.
  862:     do_test malloc-36.$zRepeat.${::n}.unlocked {
  863:       execsql {INSERT INTO t1 VALUES(3, 4)} db2
  864:     } {}
  865:     db2 close
  866:   }
  867:   catch { db2 close }
  868: }
  869: 
  870: 
  871: # Test that if an OOM error occurs, aux-data is still correctly destroyed.
  872: # This test case was causing either a memory-leak or an assert() failure
  873: # at one point, depending on the configuration.
  874: #
  875: do_malloc_test 39 -tclprep {
  876:   sqlite3 db test.db
  877: } -sqlbody {
  878:   SELECT test_auxdata('abc', 'def');
  879: } -cleanup {
  880:   db close
  881: }
  882: 
  883: # Ensure that no file descriptors were leaked.
  884: do_test malloc-99.X {
  885:   catch {db close}
  886:   set sqlite_open_file_count
  887: } {0}
  888: 
  889: puts open-file-count=$sqlite_open_file_count
  890: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>