Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | All of the malloc test cases run. Still seeing failures in malloc4.test. (CVS 4272) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
205d0b881d541db65837ce6cf44d58d6 |
User & Date: | drh 2007-08-22 22:04:37.000 |
Context
2007-08-23
| ||
02:47 | Improvements to memory leak detection. The --backtrace=NNN option is now recognized by tester.tcl. Memory leak summaries are automatically written to the file ./memleak.txt and each leak is tagged with the test in which it occurred. The quick.test script runs on Linux with no errors and no leaks. (CVS 4273) (check-in: 21f6b31097 user: drh tags: trunk) | |
2007-08-22
| ||
22:04 | All of the malloc test cases run. Still seeing failures in malloc4.test. (CVS 4272) (check-in: 205d0b881d user: drh tags: trunk) | |
20:18 | The malloc.test script now passes all tests with no errors. (CVS 4271) (check-in: db818430e9 user: drh tags: trunk) | |
Changes
Changes to src/mem2.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** ** $Id: mem2.c,v 1.7 2007/08/22 22:04:37 drh Exp $ */ /* ** This version of the memory allocator is used only if the ** SQLITE_MEMDEBUG macro is defined and SQLITE_OMIT_MEMORY_ALLOCATION ** is not defined. */ |
︙ | ︙ | |||
449 450 451 452 453 454 455 456 457 458 459 460 461 462 | mem.iFail = iFail+1; if( iRepeat>=0 ){ mem.iReset = iRepeat; } mem.iFailCnt = 0; return n; } /* ** The following two routines are used to assert that no memory ** allocations occur between one call and the next. The use of ** these routines does not change the computed results in any way. ** These routines are like asserts. */ | > > > > > > > > > | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 | mem.iFail = iFail+1; if( iRepeat>=0 ){ mem.iReset = iRepeat; } mem.iFailCnt = 0; return n; } /* ** This routine returns the number of successful mallocs remaining until ** the next simulated malloc failure. -1 is returned if no simulated ** failure is currently scheduled. */ int sqlite3_memdebug_pending(void){ return mem.iFail-1; } /* ** The following two routines are used to assert that no memory ** allocations occur between one call and the next. The use of ** these routines does not change the computed results in any way. ** These routines are like asserts. */ |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.368 2007/08/22 22:04:37 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include <assert.h> #include <string.h> /* |
︙ | ︙ | |||
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | /* ** Change the size of the pager hash table to N. N must be a power ** of two. */ static void pager_resize_hash_table(Pager *pPager, int N){ PgHdr **aHash, *pPg; assert( N>0 && (N&(N-1))==0 ); aHash = sqlite3MallocZero( sizeof(aHash[0])*N ); if( aHash==0 ){ /* Failure to rehash is not an error. It is only a performance hit. */ return; } sqlite3_free(pPager->aHash); pPager->nHash = N; pPager->aHash = aHash; | > > | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | /* ** Change the size of the pager hash table to N. N must be a power ** of two. */ static void pager_resize_hash_table(Pager *pPager, int N){ PgHdr **aHash, *pPg; assert( N>0 && (N&(N-1))==0 ); pagerLeave(pPager); aHash = sqlite3MallocZero( sizeof(aHash[0])*N ); pagerEnter(pPager); if( aHash==0 ){ /* Failure to rehash is not an error. It is only a performance hit. */ return; } sqlite3_free(pPager->aHash); pPager->nHash = N; pPager->aHash = aHash; |
︙ | ︙ | |||
2869 2870 2871 2872 2873 2874 2875 | */ for(i=0; i<=1; i++){ /* Loop through all the SQLite pagers opened by the current thread. */ Pager *pPager = sqlite3PagerList; for( ; pPager && (nReq<0 || nReleased<nReq); pPager=pPager->pNext){ PgHdr *pPg; | | > | > > | 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 | */ for(i=0; i<=1; i++){ /* Loop through all the SQLite pagers opened by the current thread. */ Pager *pPager = sqlite3PagerList; for( ; pPager && (nReq<0 || nReleased<nReq); pPager=pPager->pNext){ PgHdr *pPg; int rc = SQLITE_OK; /* In-memory databases should not appear on the pager list */ assert( !MEMDB ); /* Skip pagers that are currently in use by the b-tree layer */ if( pPager->iInUseDB ) continue; /* For each pager, try to free as many pages as possible (without ** calling fsync() if this is the first iteration of the outermost ** loop). */ while( (nReq<0 || nReleased<nReq) && SQLITE_OK==(rc = pager_recycle(pPager, i, &pPg)) && pPg ) { /* We've found a page to free. At this point the page has been ** removed from the page hash-table, free-list and synced-list ** (pFirstSynced). It is still in the all pages (pAll) list. ** Remove it from this list before freeing. ** ** Todo: Check the Pager.pStmt list to make sure this is Ok. It ** probably is though. |
︙ | ︙ | |||
3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 | pager_resize_hash_table(pPager, pPager->nHash<256 ? 256 : pPager->nHash*2); if( pPager->nHash==0 ){ rc = SQLITE_NOMEM; goto pager_allocate_out; } } pPg = sqlite3_malloc( sizeof(*pPg) + pPager->pageSize + sizeof(u32) + pPager->nExtra + MEMDB*sizeof(PgHistory) ); if( pPg==0 ){ rc = SQLITE_NOMEM; goto pager_allocate_out; } memset(pPg, 0, sizeof(*pPg)); if( MEMDB ){ memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory)); | > > | 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 | pager_resize_hash_table(pPager, pPager->nHash<256 ? 256 : pPager->nHash*2); if( pPager->nHash==0 ){ rc = SQLITE_NOMEM; goto pager_allocate_out; } } pagerLeave(pPager); pPg = sqlite3_malloc( sizeof(*pPg) + pPager->pageSize + sizeof(u32) + pPager->nExtra + MEMDB*sizeof(PgHistory) ); pagerEnter(pPager); if( pPg==0 ){ rc = SQLITE_NOMEM; goto pager_allocate_out; } memset(pPg, 0, sizeof(*pPg)); if( MEMDB ){ memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory)); |
︙ | ︙ | |||
3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 | int rc; assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); assert( pPager->aInJournal==0 ); sqlite3PagerPagecount(pPager); pPager->aInJournal = sqlite3MallocZero( pPager->dbSize/8 + 1 ); if( pPager->aInJournal==0 ){ rc = SQLITE_NOMEM; goto failed_to_open_journal; } if( pPager->tempFile ){ flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); | > > | 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 | int rc; assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); assert( pPager->aInJournal==0 ); sqlite3PagerPagecount(pPager); pagerLeave(pPager); pPager->aInJournal = sqlite3MallocZero( pPager->dbSize/8 + 1 ); pagerEnter(pPager); if( pPager->aInJournal==0 ){ rc = SQLITE_NOMEM; goto failed_to_open_journal; } if( pPager->tempFile ){ flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); |
︙ | ︙ | |||
3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 | ** by this connection. Instead of deleting the journal file it was ** kept open and truncated to 0 bytes. */ assert( pPager->nRec==0 ); assert( pPager->origDbSize==0 ); assert( pPager->aInJournal==0 ); sqlite3PagerPagecount(pPager); pPager->aInJournal = sqlite3MallocZero( pPager->dbSize/8 + 1 ); if( !pPager->aInJournal ){ rc = SQLITE_NOMEM; }else{ pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); } } | > > | 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 | ** by this connection. Instead of deleting the journal file it was ** kept open and truncated to 0 bytes. */ assert( pPager->nRec==0 ); assert( pPager->origDbSize==0 ); assert( pPager->aInJournal==0 ); sqlite3PagerPagecount(pPager); pagerLeave(pPager); pPager->aInJournal = sqlite3MallocZero( pPager->dbSize/8 + 1 ); pagerEnter(pPager); if( !pPager->aInJournal ){ rc = SQLITE_NOMEM; }else{ pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); } } |
︙ | ︙ | |||
4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 | return SQLITE_OK; } if( !pPager->journalOpen ){ pPager->stmtAutoopen = 1; return SQLITE_OK; } assert( pPager->journalOpen ); pPager->aInStmt = sqlite3MallocZero( pPager->dbSize/8 + 1 ); if( pPager->aInStmt==0 ){ /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */ return SQLITE_NOMEM; } #ifndef NDEBUG rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; | > > | 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 | return SQLITE_OK; } if( !pPager->journalOpen ){ pPager->stmtAutoopen = 1; return SQLITE_OK; } assert( pPager->journalOpen ); pagerLeave(pPager); pPager->aInStmt = sqlite3MallocZero( pPager->dbSize/8 + 1 ); pagerEnter(pPager); if( pPager->aInStmt==0 ){ /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */ return SQLITE_NOMEM; } #ifndef NDEBUG rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; |
︙ | ︙ |
Changes to src/test_malloc.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** ** $Id: test_malloc.c,v 1.3 2007/08/22 22:04:37 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> #include <assert.h> |
︙ | ︙ | |||
224 225 226 227 228 229 230 | } #endif return TCL_OK; } /* | | | | > | > > > > > > > > > > > > > > > > > > > > > > > | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | } #endif return TCL_OK; } /* ** Usage: sqlite3_memdebug_fail COUNTER ?REPEAT? ** ** Arrange for a simulated malloc() failure after COUNTER successes. ** If REPEAT is 1 then all subsequent malloc()s fail. If REPEAT is ** 0 then only a single failure occurs. ** ** Each call to this routine overrides the prior counter value. ** This routine returns the number of simulated failures that have ** happened since the previous call to this routine. ** ** To disable simulated failures, use a COUNTER of -1. */ static int test_memdebug_fail( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int iFail; int iRepeat; int nFail = 0; if( objc!=3 && objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?REPEAT?"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR; if( objc==3 ){ if( Tcl_GetIntFromObj(interp, objv[2], &iRepeat) ) return TCL_ERROR; }else{ iRepeat = -1; } #ifdef SQLITE_MEMDEBUG { extern int sqlite3_memdebug_fail(int,int); nFail = sqlite3_memdebug_fail(iFail, iRepeat); } #endif Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail)); return TCL_OK; } /* ** Usage: sqlite3_memdebug_pending ** ** Return the number of successful mallocs remaining before the ** next simulated failure. Return -1 if no simulated failure is ** currently scheduled. */ static int test_memdebug_pending( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ extern int sqlite3_memdebug_pending(void); Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_pending())); return TCL_OK; } /* ** Register commands with the TCL interpreter. */ int Sqlitetest_malloc_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; } aObjCmd[] = { { "sqlite3_malloc", test_malloc }, { "sqlite3_realloc", test_realloc }, { "sqlite3_free", test_free }, { "sqlite3_memory_used", test_memory_used }, { "sqlite3_memory_highwater", test_memory_highwater }, { "sqlite3_memdebug_backtrace", test_memdebug_backtrace }, { "sqlite3_memdebug_dump", test_memdebug_dump }, { "sqlite3_memdebug_fail", test_memdebug_fail }, { "sqlite3_memdebug_pending", test_memdebug_pending }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); } return TCL_OK; } |
Changes to test/malloc2.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2005 March 18 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file attempts to check that the library can recover from a malloc() # failure when sqlite3_global_recover() is invoked. # | > > > > > | | | | | < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # 2005 March 18 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This file attempts to check that the library can recover from a malloc() # failure when sqlite3_global_recover() is invoked. # # (Later:) The sqlite3_global_recover() interface is now a no-op. # Recovery from malloc() failures is automatic. But we keep these # tests around because you can never have too many test cases. # # $Id: malloc2.test,v 1.6 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } # Generate a checksum based on the contents of the database. If the # checksum of two databases is the same, and the integrity-check passes # for both, the two databases are identical. # proc cksum {db} { |
︙ | ︙ | |||
61 62 63 64 65 66 67 | array set ::mallocopts $args set sum [cksum db] for {set ::n 1} {true} {incr ::n} { # Run the SQL. Malloc number $::n is set to fail. A malloc() failure # may or may not be reported. | | < | | < | | | | | | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | array set ::mallocopts $args set sum [cksum db] for {set ::n 1} {true} {incr ::n} { # Run the SQL. Malloc number $::n is set to fail. A malloc() failure # may or may not be reported. sqlite3_memdebug_fail $::n 1 do_test malloc2-$tn.$::n.2 { set res [catchsql [string trim $::mallocopts(-sql)]] set rc [expr { 0==[string compare $res {1 {out of memory}}] || 0==[lindex $res 0] }] if {$rc!=1} { puts "Error: $res" } set rc } {1} # If $::n is greater than the number of malloc() calls required to # execute the SQL, then this test is finished. Break out of the loop. set nFail [sqlite3_memdebug_fail -1 -1] if {$nFail==0} break # Nothing should work now, because the allocator should refuse to # allocate any memory. # # Update: SQLite now automatically recovers from a malloc() failure. # So the statement in the test below would work. if 0 { do_test malloc2-$tn.$::n.3 { catchsql {SELECT 'nothing should work'} } {1 {out of memory}} } # Recover from the malloc failure. # # Update: The new malloc() failure handling means that a transaction may # still be active even if a malloc() has failed. But when these tests were # written this was not the case. So do a manual ROLLBACK here so that the # tests pass. |
︙ | ︙ | |||
114 115 116 117 118 119 120 | # Checksum the database. do_test malloc2-$tn.$::n.5 { cksum db } $sum integrity_check malloc2-$tn.$::n.6 | | | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | # Checksum the database. do_test malloc2-$tn.$::n.5 { cksum db } $sum integrity_check malloc2-$tn.$::n.6 if {$::nErr>1} return } unset ::mallocopts } do_test malloc2.1.setup { execsql { CREATE TABLE abc(a, b, c); |
︙ | ︙ |
Changes to test/malloc3.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # # This file contains tests to ensure that the library handles malloc() failures # correctly. The emphasis of these tests are the _prepare(), _step() and # _finalize() calls. # | | < > > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # #*********************************************************************** # # This file contains tests to ensure that the library handles malloc() failures # correctly. The emphasis of these tests are the _prepare(), _step() and # _finalize() calls. # # $Id: malloc3.test,v 1.11 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } #-------------------------------------------------------------------------- # NOTES ON RECOVERING FROM A MALLOC FAILURE |
︙ | ︙ | |||
555 556 557 558 559 560 561 | incr pc } -sql { set ::rollback_hook_count 0 set ac [sqlite3_get_autocommit $::DB] ;# Auto-Commit | | > | < | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 | incr pc } -sql { set ::rollback_hook_count 0 set ac [sqlite3_get_autocommit $::DB] ;# Auto-Commit sqlite3_memdebug_fail $iFail 1 set rc [catch {db eval [lindex $v 1]} msg] ;# True error occurs set nac [sqlite3_get_autocommit $::DB] ;# New Auto-Commit if {$rc != 0 && $nac && !$ac} { # Before [db eval] the auto-commit flag was clear. Now it # is set. Since an error occured we assume this was not a # commit - therefore a rollback occured. Check that the # rollback-hook was invoked. do_test malloc3-rollback_hook.$iterid { set ::rollback_hook_count } {1} } set nFail [sqlite3_memdebug_fail -1 -1] if {$rc == 0} { # Successful execution of sql. Our "mallocs-until-failure" # count should be greater than 0. Otherwise a malloc() failed # and the error was not reported. if {$nFail>0} { error "Unreported malloc() failure" } if {$ac && !$nac} { # Before the [db eval] the auto-commit flag was set, now it # is clear. We can deduce that a "BEGIN" statement has just # been successfully executed. set begin_pc $pc } incr pc set iFail 1 integrity_check "malloc3-(integrity).$iterid" } elseif {[regexp {.*out of memory} $msg]} { # Out of memory error, as expected integrity_check "malloc3-(integrity).$iterid" incr iFail if {$nac && !$ac} { |
︙ | ︙ | |||
634 635 636 637 638 639 640 | } # Turn of the Tcl interface's prepared statement caching facility. db cache size 0 run_test $::run_test_script 9 1 # run_test [lrange $::run_test_script 0 3] 0 63 | | < < | 635 636 637 638 639 640 641 642 643 644 645 | } # Turn of the Tcl interface's prepared statement caching facility. db cache size 0 run_test $::run_test_script 9 1 # run_test [lrange $::run_test_script 0 3] 0 63 sqlite3_memdebug_fail -1 -1 db close finish_test |
Changes to test/malloc4.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # # This file contains tests to ensure that the library handles malloc() failures # correctly. The emphasis in this file is on sqlite3_column_XXX() APIs. # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | # May you share freely, never taking more than you give. # #*********************************************************************** # # This file contains tests to ensure that the library handles malloc() failures # correctly. The emphasis in this file is on sqlite3_column_XXX() APIs. # # $Id: malloc4.test,v 1.4 2007/08/22 22:04:37 drh Exp $ #--------------------------------------------------------------------------- # NOTES ON EXPECTED BEHAVIOUR # # [193] When a memory allocation failure occurs during sqlite3_column_name(), # sqlite3_column_name16(), sqlite3_column_decltype(), or # sqlite3_column_decltype16() the function shall return NULL. # #--------------------------------------------------------------------------- set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. if {[info command sqlite3_memdebug_pending]==""} { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } ifcapable !utf16 { finish_test return } proc do_stmt_test {id sql} { set ::sql $sql set go 1 for {set n 1} {$go} {incr n} { set testid "malloc4-$id.$n" # Prepare the statement do_test ${testid}.1 { set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] expr [string length $::STMT] > 0 } {1} # Set the Nth malloc() to fail. sqlite3_memdebug_fail $n 1 # Test malloc failure in the _name(), _name16(), decltype() and # decltype16() APIs. Calls that occur after the malloc() failure should # return NULL. No error is raised though. # # ${testid}.2.1 - Call _name() # ${testid}.2.2 - Call _name16() # ${testid}.2.3 - Call _name() # ${testid}.2.4 - Check that the return values of the above three calls are # consistent with each other and with the simulated # malloc() failures. # # Because the code that implements the _decltype() and _decltype16() APIs # is the same as the _name() and _name16() implementations, we don't worry # about explicitly testing them. # do_test ${testid}.2.1 { set mf1 [expr [sqlite3_memdebug_pending] <= 0] set ::name8 [sqlite3_column_name $::STMT 0] set mf2 [expr [sqlite3_memdebug_pending] <= 0] expr {$mf1 == $mf2 || $::name8 == ""} } {1} do_test ${testid}.2.2 { set mf1 [expr [sqlite3_memdebug_pending] <= 0] set ::name16 [sqlite3_column_name16 $::STMT 0] set ::name16 [encoding convertfrom unicode $::name16] set ::name16 [string range $::name16 0 end-1] set mf2 [expr [sqlite3_memdebug_pending] <= 0] expr {$mf1 == $mf2 || $::name16 == ""} } {1} do_test ${testid}.2.3 { set mf1 [expr [sqlite3_memdebug_pending] <= 0] set ::name8_2 [sqlite3_column_name $::STMT 0] set mf2 [expr [sqlite3_memdebug_pending] <= 0] expr {$mf1 == $mf2 || $::name8_2 == ""} } {1} set ::mallocFailed [expr [sqlite3_memdebug_pending] <= 0] do_test ${testid}.2.4 { expr { $::name8 == $::name8_2 && $::name16 == $::name8 && !$::mallocFailed || $::name8 == $::name8_2 && $::name16 == "" && $::mallocFailed || $::name8 == $::name16 && $::name8_2 == "" && $::mallocFailed || $::name8_2 == $::name16 && $::name8 == "" && $::mallocFailed } } {1} # Step the statement so that we can call _text() and _text16(). Before # running sqlite3_step(), make sure that malloc() is not about to fail. # Memory allocation failures that occur within sqlite3_step() are tested # elsewhere. set mf [sqlite3_memdebug_pending] sqlite3_memdebug_fail -1 do_test ${testid}.3 { sqlite3_step $::STMT } {SQLITE_ROW} sqlite3_memdebug_fail $mf # Test for malloc() failures within _text() and _text16(). # do_test ${testid}.4.1 { set ::text8 [sqlite3_column_text $::STMT 0] set mf [expr [sqlite3_memdebug_pending] <= 0 && !$::mallocFailed] expr {$mf==0 || $::text8 == ""} } {1} do_test ${testid}.4.2 { set ::text16 [sqlite3_column_text16 $::STMT 0] set ::text16 [encoding convertfrom unicode $::text16] set ::text16 [string range $::text16 0 end-1] set mf [expr [sqlite3_memdebug_pending] <= 0 && !$::mallocFailed] expr {$mf==0 || $::text16 == ""} } {1} do_test ${testid}.4.3 { set ::text8_2 [sqlite3_column_text $::STMT 0] set mf [expr [sqlite3_memdebug_pending] <= 0 && !$::mallocFailed] expr {$mf==0 || $::text8_2 == "" || ($::text16 == "" && $::text8 != "")} } {1} # Test for malloc() failures within _int(), _int64() and _real(). The only # way this can occur is if the string has to be translated from UTF-16 to # UTF-8 before being converted to a numeric value. do_test ${testid}.4.4.1 { set mf [sqlite3_memdebug_pending] sqlite3_memdebug_fail -1 sqlite3_column_text16 $::STMT 0 sqlite3_memdebug_fail $mf sqlite3_column_int $::STMT 0 } {0} do_test ${testid}.4.5 { set mf [sqlite3_memdebug_pending] sqlite3_memdebug_fail -1 sqlite3_column_text16 $::STMT 0 sqlite3_memdebug_fail $mf sqlite3_column_int64 $::STMT 0 } {0} do_test ${testid}.4.6 { set mf [sqlite3_memdebug_pending] sqlite3_memdebug_fail -1 sqlite3_column_text16 $::STMT 0 sqlite3_memdebug_fail $mf sqlite3_column_double $::STMT 0 } {0.0} set mallocFailedAfterStep [expr \ [sqlite3_memdebug_pending] <= 0 && !$::mallocFailed ] sqlite3_memdebug_fail -1 # Test that if a malloc() failed the next call to sqlite3_step() returns # SQLITE_ERROR. If malloc() did not fail, it should return SQLITE_DONE. # do_test ${testid}.5 { sqlite3_step $::STMT } [expr {$mallocFailedAfterStep ? "SQLITE_ERROR" : "SQLITE_DONE"}] do_test ${testid}.6 { sqlite3_finalize $::STMT } [expr {$mallocFailedAfterStep ? "SQLITE_NOMEM" : "SQLITE_OK"}] if {$::mallocFailed == 0 && $mallocFailedAfterStep == 0} { sqlite3_memdebug_fail -1 set go 0 } } } execsql { CREATE TABLE tbl( the_first_reasonably_long_column_name that_also_has_quite_a_lengthy_type ); INSERT INTO tbl VALUES( 'An extra long string. Far too long to be stored in NBFS bytes.' ); } do_stmt_test 1 "SELECT * FROM tbl" sqlite3_memdebug_fail -1 finish_test |
Changes to test/malloc5.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # # This file contains test cases focused on the two memory-management APIs, # sqlite3_soft_heap_limit() and sqlite3_release_memory(). # | | < > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # May you share freely, never taking more than you give. # #*********************************************************************** # # This file contains test cases focused on the two memory-management APIs, # sqlite3_soft_heap_limit() and sqlite3_release_memory(). # # $Id: malloc5.test,v 1.13 2007/08/22 22:04:37 drh Exp $ #--------------------------------------------------------------------------- # NOTES ON EXPECTED BEHAVIOUR # #--------------------------------------------------------------------------- set testdir [file dirname $argv0] source $testdir/tester.tcl db close # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } # Skip these tests if OMIT_MEMORY_MANAGEMENT was defined at compile time. ifcapable !memorymanage { |
︙ | ︙ | |||
170 171 172 173 174 175 176 | do_test malloc5-3.2 { concat \ [execsql {SELECT * FROM abc; COMMIT}] \ [execsql {SELECT * FROM def; COMMIT} db2] } {1 2 3 4 5 6 7 8 9 10 11 12} db2 close | | | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | do_test malloc5-3.2 { concat \ [execsql {SELECT * FROM abc; COMMIT}] \ [execsql {SELECT * FROM def; COMMIT} db2] } {1 2 3 4 5 6 7 8 9 10 11 12} db2 close puts "Highwater mark: [sqlite3_memory_highwater]" # The following two test cases each execute a transaction in which # 10000 rows are inserted into table abc. The first test case is used # to ensure that more than 1MB of dynamic memory is used to perform # the transaction. # # The second test case sets the "soft-heap-limit" to 100,000 bytes (0.1 MB) |
︙ | ︙ | |||
194 195 196 197 198 199 200 | do_test malloc5-4.1 { execsql {BEGIN;} execsql {DELETE FROM abc;} for {set i 0} {$i < 10000} {incr i} { execsql "INSERT INTO abc VALUES($i, $i, '[string repeat X 100]');" } execsql {COMMIT;} | | | | < > | | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | do_test malloc5-4.1 { execsql {BEGIN;} execsql {DELETE FROM abc;} for {set i 0} {$i < 10000} {incr i} { execsql "INSERT INTO abc VALUES($i, $i, '[string repeat X 100]');" } execsql {COMMIT;} set nMaxBytes [sqlite3_memory_highwater 1] puts -nonewline " (Highwater mark: $nMaxBytes) " expr $nMaxBytes > 1000000 } {1} do_test malloc5-4.2 { sqlite3_release_memory sqlite3_soft_heap_limit 100000 sqlite3_memory_highwater 1 execsql {BEGIN;} for {set i 0} {$i < 10000} {incr i} { execsql "INSERT INTO abc VALUES($i, $i, '[string repeat X 100]');" } execsql {COMMIT;} set nMaxBytes [sqlite3_memory_highwater 1] puts -nonewline " (Highwater mark: $nMaxBytes) " expr $nMaxBytes <= 100000 } {1} do_test malloc5-4.3 { # Check that the content of table abc is at least roughly as expected. execsql { SELECT count(*), sum(a), sum(b) FROM abc; } } [list 20000 [expr int(20000.0 * 4999.5)] [expr int(20000.0 * 4999.5)]] |
︙ | ︙ |
Changes to test/malloc6.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2006 June 25 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file attempts to check the library in an out-of-memory situation. | < < < < | | | < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # 2006 June 25 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file attempts to check the library in an out-of-memory situation. # # $Id: malloc6.test,v 1.2 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } source $testdir/malloc_common.tcl set sqlite_os_trace 0 do_malloc_test malloc6-1 -tclprep { db close } -tclbody { if {[catch {sqlite3 db test.db}]} { error "out of memory" } } -sqlbody { DROP TABLE IF EXISTS t1; |
︙ | ︙ | |||
145 146 147 148 149 150 151 | # Ensure that no file descriptors were leaked. do_test malloc6-1.X { catch {db close} set sqlite_open_file_count } {0} | < | 47 48 49 50 51 52 53 54 | # Ensure that no file descriptors were leaked. do_test malloc6-1.X { catch {db close} set sqlite_open_file_count } {0} finish_test |
Changes to test/malloc7.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2006 July 26 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl) # added to expose a bug in out-of-memory handling for sqlite3_prepare16(). # | | | | < | < < | < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | # 2006 July 26 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl) # added to expose a bug in out-of-memory handling for sqlite3_prepare16(). # # $Id: malloc7.test,v 1.3 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } source $testdir/malloc_common.tcl do_malloc_test malloc7-1 -sqlprep { CREATE TABLE t1(a,b,c,d); CREATE INDEX i1 ON t1(b,c); } -tclbody { set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"] append sql16 "\00\00" set nbyte [string length $sql16] set ::STMT [sqlite3_prepare16 db $sql16 $nbyte DUMMY] sqlite3_finalize $::STMT } # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} puts open-file-count=$sqlite_open_file_count finish_test |
Changes to test/malloc8.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2007 April 25 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl) # added to expose a bug in out-of-memory handling for sqlite3_value_text() # | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < | < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | # 2007 April 25 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl) # added to expose a bug in out-of-memory handling for sqlite3_value_text() # # $Id: malloc8.test,v 1.4 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } source $testdir/malloc_common.tcl # The setup is a database with UTF-16 encoding that contains a single # large string. We will be running lots of queries against this # database. Because we will be extracting the string as UTF-8, there # is a type conversion that occurs and thus an opportunity for malloc() # to fail and for sqlite3_value_text() to return 0 even though # sqlite3_value_type() returns SQLITE_TEXT. # do_malloc_test malloc8-1 -sqlprep { PRAGMA encoding='UTF-16'; CREATE TABLE t1(a); INSERT INTO t1 VALUES('0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ'); } -sqlbody { SELECT lower(a), upper(a), quote(a), trim(a), trim('x',a) FROM t1; } do_malloc_test malloc8-2 -sqlprep { PRAGMA encoding='UTF-16'; CREATE TABLE t1(a); INSERT INTO t1 VALUES('0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ'); } -sqlbody { SELECT replace(a,'x','y'), replace('x',a,'y'), replace('x','y',a) FROM t1; } do_malloc_test malloc8-3 -sqlprep { PRAGMA encoding='UTF-16'; CREATE TABLE t1(a); INSERT INTO t1 VALUES('0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ'); } -sqlbody { SELECT length(a), substr(a, 4, 4) FROM t1; } do_malloc_test malloc8-4 -sqlprep { PRAGMA encoding='UTF-16'; CREATE TABLE t1(a); INSERT INTO t1 VALUES('0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ'); } -sqlbody { SELECT julianday(a,a) FROM t1; } do_malloc_test malloc8-5 -sqlprep { PRAGMA encoding='UTF-16'; CREATE TABLE t1(a); INSERT INTO t1 VALUES('0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ'); } -sqlbody { SELECT 1 FROM t1 WHERE a LIKE 'hello' ESCAPE NULL; } do_malloc_test malloc8-6 -sqlprep { PRAGMA encoding='UTF-16'; CREATE TABLE t1(a); INSERT INTO t1 VALUES('0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ'); } -sqlbody { SELECT hex(randomblob(100)); } # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} finish_test |
Changes to test/malloc9.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2007 April 30 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl) # added to expose a bug in out-of-memory handling for sqlite3_prepare(). # | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # 2007 April 30 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl) # added to expose a bug in out-of-memory handling for sqlite3_prepare(). # # $Id: malloc9.test,v 1.2 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } source $testdir/malloc_common.tcl do_malloc_test 1 -tclprep { set sql {CREATE TABLE t1(x)} set sqlbytes [string length $sql] append sql {; INSERT INTO t1 VALUES(1)} } -tclbody { if {[catch {sqlite3_prepare db $sql $sqlbytes TAIL} STMT]} { |
︙ | ︙ | |||
134 135 136 137 138 139 140 | # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} | < | 44 45 46 47 48 49 50 51 | # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} finish_test |
Changes to test/mallocA.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # 2007 April 30 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl). # | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | # 2007 April 30 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl). # # $Id: mallocA.test,v 1.3 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } source $testdir/malloc_common.tcl # Construct a test database # file delete -force test.db.bu db eval { CREATE TABLE t1(a COLLATE NOCASE,b,c); INSERT INTO t1 VALUES(1,2,3); INSERT INTO t1 VALUES(1,2,4); INSERT INTO t1 VALUES(2,3,4); CREATE INDEX t1i1 ON t1(a); CREATE INDEX t1i2 ON t1(b,c); CREATE TABLE t2(x,y,z); } db close file copy test.db test.db.bu do_malloc_test 1 -testdb test.db.bu -sqlbody { ANALYZE } do_malloc_test 2 -testdb test.db.bu -sqlbody { REINDEX; } do_malloc_test 3 -testdb test.db.bu -sqlbody { REINDEX t1; } do_malloc_test 4 -testdb test.db.bu -sqlbody { REINDEX main.t1; } do_malloc_test 5 -testdb test.db.bu -sqlbody { REINDEX nocase; } # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} file delete -force test.db.bu finish_test |
Changes to test/mallocB.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl). # These were all discovered by fuzzy generation of SQL. Apart from # that they have little in common. # # | | | > < | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | # #*********************************************************************** # This file contains additional out-of-memory checks (see malloc.tcl). # These were all discovered by fuzzy generation of SQL. Apart from # that they have little in common. # # # $Id: mallocB.test,v 1.4 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } source $testdir/malloc_common.tcl do_malloc_test mallocB-1 -sqlbody {SELECT - 456} do_malloc_test mallocB-2 -sqlbody {SELECT - 456.1} do_malloc_test mallocB-3 -sqlbody {SELECT random()} do_malloc_test mallocB-4 -sqlbody {SELECT zeroblob(1000)} do_malloc_test mallocB-5 -sqlbody {SELECT * FROM (SELECT 1) GROUP BY 1;} # The following test checks that there are no resource leaks following a # malloc() failure in sqlite3_set_auxdata(). # # Note: This problem was not discovered by fuzzy generation of SQL. Not # that it really matters. # do_malloc_test mallocB-6 -sqlbody { SELECT test_auxdata('hello world'); } finish_test |
Changes to test/mallocC.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # # This file tests aspects of the malloc failure while parsing # CREATE TABLE statements in auto_vacuum mode. # | | | | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # May you share freely, never taking more than you give. # #*********************************************************************** # # This file tests aspects of the malloc failure while parsing # CREATE TABLE statements in auto_vacuum mode. # # $Id: mallocC.test,v 1.3 2007/08/22 22:04:37 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # ifcapable !memdebug { puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } # Generate a checksum based on the contents of the database. If the # checksum of two databases is the same, and the integrity-check passes # for both, the two databases are identical. # proc cksum {db} { |
︙ | ︙ | |||
57 58 59 60 61 62 63 | array set ::mallocopts $args set sum [cksum db] for {set ::n 1} {true} {incr ::n} { # Run the SQL. Malloc number $::n is set to fail. A malloc() failure # may or may not be reported. | | | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | array set ::mallocopts $args set sum [cksum db] for {set ::n 1} {true} {incr ::n} { # Run the SQL. Malloc number $::n is set to fail. A malloc() failure # may or may not be reported. sqlite3_memdebug_fail $::n 1 do_test mallocC-$tn.$::n.1 { set res [catchsql [string trim $::mallocopts(-sql)]] set rc [expr { 0==[string compare $res {1 {out of memory}}] || 0==[lindex $res 0] }] if {$rc!=1} { puts "Error: $res" } set rc } {1} # If $::n is greater than the number of malloc() calls required to # execute the SQL, then this test is finished. Break out of the loop. set nFail [sqlite3_memdebug_fail -1 -1] if {$nFail==0} { break } # Recover from the malloc failure. # # Update: The new malloc() failure handling means that a transaction may # still be active even if a malloc() has failed. But when these tests were |
︙ | ︙ |
Changes to test/malloc_common.tcl.
︙ | ︙ | |||
44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # system. Then open (empty database) "test.db" with the handle [db]. # catch {db close} catch {file delete -force test.db} catch {file delete -force test.db-journal} catch {file delete -force test2.db} catch {file delete -force test2.db-journal} catch {sqlite3 db test.db} # Execute any -tclprep and -sqlprep scripts. # if {[info exists ::mallocopts(-tclprep)]} { eval $::mallocopts(-tclprep) } | > > > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | # system. Then open (empty database) "test.db" with the handle [db]. # catch {db close} catch {file delete -force test.db} catch {file delete -force test.db-journal} catch {file delete -force test2.db} catch {file delete -force test2.db-journal} if {[info exists ::mallocopts(-testdb)]} { file copy $::mallocopts(-testdb) test.db } catch {sqlite3 db test.db} # Execute any -tclprep and -sqlprep scripts. # if {[info exists ::mallocopts(-tclprep)]} { eval $::mallocopts(-tclprep) } |
︙ | ︙ |
Changes to test/tester.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # # $Id: tester.tcl,v 1.86 2007/08/22 22:04:37 drh Exp $ # Make sure tclsqlite3 was compiled correctly. Abort now with an # error message if not. # if {[sqlite3 -tcl-uses-utf]} { if {"\u1234"=="u1234"} { puts stderr "***** BUILD PROBLEM *****" |
︙ | ︙ | |||
188 189 190 191 192 193 194 | global nTest nErr sqlite_open_file_count if {$nErr==0} memleak_check catch {db close} catch {db2 close} catch {db3 close} | < < < | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | global nTest nErr sqlite_open_file_count if {$nErr==0} memleak_check catch {db close} catch {db2 close} catch {db3 close} sqlite3 db {} # sqlite3_clear_tsd_memdebug db close set heaplimit [sqlite3_soft_heap_limit] if {$heaplimit!=$::soft_limit} { puts "soft-heap-limit changed by this script\ from $::soft_limit to $heaplimit" |
︙ | ︙ | |||
567 568 569 570 571 572 573 | fconfigure $t -translation binary puts -nonewline $t [read $f [file size $from]] close $t close $f } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 564 565 566 567 568 569 570 571 572 573 | fconfigure $t -translation binary puts -nonewline $t [read $f [file size $from]] close $t close $f } } # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set # to non-zero, then set the global variable $AUTOVACUUM to 1. set AUTOVACUUM $sqlite_options(default_autovacuum) |