Annotation of embedaddon/sqlite3/test/malloc.test, revision 1.1.1.1

1.1       misho       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.81 2009/06/24 13:13:45 drh 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>