persistentstorage/sqlite3api/TEST/TclScript/mallocC.test
changeset 0 08ec8eefde2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sqlite3api/TEST/TclScript/mallocC.test	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,107 @@
+# 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.9 2008/02/18 22:24:58 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
+  if {$::nErr>1} return
+  }
+  unset ::mallocopts
+}
+
+sqlite3_extended_result_codes db 1
+
+execsql {
+  PRAGMA auto_vacuum=1;
+  CREATE TABLE t0(a, b, c);
+}
+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