| # 2007 Aug 13 |
| # |
| # 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 tests aspects of the malloc failure while parsing |
| # CREATE TABLE statements in auto_vacuum mode. |
| # |
| # $Id: mallocC.test,v 1.10 2009/04/11 16:27:50 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. |
| # |
| if {!$MEMDEBUG} { |
| puts "Skipping mallocC tests: not compiled with -DSQLITE_MEMDEBUG..." |
| finish_test |
| return |
| } |
| |
| proc do_mallocC_test {tn args} { |
| array set ::mallocopts $args |
| #set sum [allcksum 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 -repeat 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}}] || |
| [db errorcode] == 3082 || |
| 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] |
| 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 |
| # written this was not the case. So do a manual ROLLBACK here so that the |
| # tests pass. |
| do_test mallocC-$tn.$::n.2 { |
| catch { |
| execsql { |
| ROLLBACK; |
| } |
| } |
| expr 0 |
| } {0} |
| |
| # Checksum the database. |
| #do_test mallocC-$tn.$::n.3 { |
| # allcksum db |
| #} $sum |
| |
| #integrity_check mallocC-$tn.$::n.4 |
| } |
| unset ::mallocopts |
| } |
| |
| sqlite3_extended_result_codes db 1 |
| |
| execsql { |
| PRAGMA auto_vacuum=1; |
| CREATE TABLE t0(a, b, c); |
| } |
| |
| # The number of memory allocation failures is different on 64-bit |
| # and 32-bit systems due to larger structures on 64-bit systems |
| # overflowing the lookaside more often. To debug problems, it is |
| # sometimes helpful to reduce the size of the lookaside allocation |
| # blocks. But this is normally disabled. |
| # |
| if {0} { |
| db close |
| sqlite3_shutdown |
| sqlite3_config_lookaside 50 500 |
| sqlite3_initialize |
| autoinstall_test_functions |
| sqlite3 db test.db |
| } |
| |
| do_mallocC_test 1 -sql { |
| BEGIN; |
| -- Allocate 32 new root pages. This will exercise the 'extract specific |
| -- page from the freelist' code when in auto-vacuum mode (see the |
| -- allocatePage() routine in btree.c). |
| CREATE TABLE t1(a UNIQUE, b UNIQUE, c UNIQUE); |
| CREATE TABLE t2(a UNIQUE, b UNIQUE, c UNIQUE); |
| CREATE TABLE t3(a UNIQUE, b UNIQUE, c UNIQUE); |
| CREATE TABLE t4(a UNIQUE, b UNIQUE, c UNIQUE); |
| CREATE TABLE t5(a UNIQUE, b UNIQUE, c UNIQUE); |
| CREATE TABLE t6(a UNIQUE, b UNIQUE, c UNIQUE); |
| CREATE TABLE t7(a UNIQUE, b UNIQUE, c UNIQUE); |
| CREATE TABLE t8(a UNIQUE, b UNIQUE, c UNIQUE); |
| |
| ROLLBACK; |
| } |
| |
| finish_test |