xref: /sqlite-3.40.0/test/mallocC.test (revision 4152e677)
1# 2007 Aug 13
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 tests aspects of the malloc failure while parsing
13# CREATE TABLE statements in auto_vacuum mode.
14#
15# $Id: mallocC.test,v 1.6 2007/09/12 17:01:45 danielk1977 Exp $
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20# Only run these tests if memory debugging is turned on.
21#
22ifcapable !memdebug||!compound {
23   puts "Skipping mallocC tests: not compiled with -DSQLITE_MEMDEBUG..."
24   finish_test
25   return
26}
27
28# Generate a checksum based on the contents of the database. If the
29# checksum of two databases is the same, and the integrity-check passes
30# for both, the two databases are identical.
31#
32proc cksum {db} {
33  set ret [list]
34  ifcapable tempdb {
35    set sql {
36      SELECT name FROM sqlite_master WHERE type = 'table' UNION
37      SELECT name FROM sqlite_temp_master WHERE type = 'table' UNION
38      SELECT 'sqlite_master' UNION
39      SELECT 'sqlite_temp_master'
40    }
41  } else {
42    set sql {
43      SELECT name FROM sqlite_master WHERE type = 'table' UNION
44      SELECT 'sqlite_master'
45    }
46  }
47  set tbllist [$db eval $sql]
48  set txt {}
49  foreach tbl $tbllist {
50    append txt [$db eval "SELECT * FROM $tbl"]
51  }
52  # puts txt=$txt
53  return [md5 $txt]
54}
55
56proc do_mallocC_test {tn args} {
57  array set ::mallocopts $args
58  set sum [cksum db]
59
60  for {set ::n 1} {true} {incr ::n} {
61
62    # Run the SQL. Malloc number $::n is set to fail. A malloc() failure
63    # may or may not be reported.
64    sqlite3_memdebug_fail $::n -repeat 1
65    do_test mallocC-$tn.$::n.1 {
66      set res [catchsql [string trim $::mallocopts(-sql)]]
67      set rc [expr {
68        0==[string compare $res {1 {out of memory}}] ||
69        0==[lindex $res 0]
70      }]
71      if {$rc!=1} {
72        puts "Error: $res"
73      }
74      set rc
75    } {1}
76
77    # If $::n is greater than the number of malloc() calls required to
78    # execute the SQL, then this test is finished. Break out of the loop.
79    set nFail [sqlite3_memdebug_fail -1]
80    if {$nFail==0} {
81      break
82    }
83
84    # Recover from the malloc failure.
85    #
86    # Update: The new malloc() failure handling means that a transaction may
87    # still be active even if a malloc() has failed. But when these tests were
88    # written this was not the case. So do a manual ROLLBACK here so that the
89    # tests pass.
90    do_test mallocC-$tn.$::n.2 {
91      catch {
92        execsql {
93          ROLLBACK;
94        }
95      }
96      expr 0
97    } {0}
98
99    # Checksum the database.
100    #do_test mallocC-$tn.$::n.3 {
101    #  cksum db
102    #} $sum
103
104    #integrity_check mallocC-$tn.$::n.4
105  if {$::nErr>1} return
106  }
107  unset ::mallocopts
108}
109
110execsql {
111  PRAGMA auto_vacuum=1;
112  CREATE TABLE t0(a, b, c);
113}
114do_mallocC_test 1 -sql {
115  BEGIN;
116  -- Allocate 32 new root pages. This will exercise the 'extract specific
117  -- page from the freelist' code when in auto-vacuum mode (see the
118  -- allocatePage() routine in btree.c).
119  CREATE TABLE t1(a UNIQUE, b UNIQUE, c UNIQUE);
120  CREATE TABLE t2(a UNIQUE, b UNIQUE, c UNIQUE);
121  CREATE TABLE t3(a UNIQUE, b UNIQUE, c UNIQUE);
122  CREATE TABLE t4(a UNIQUE, b UNIQUE, c UNIQUE);
123  CREATE TABLE t5(a UNIQUE, b UNIQUE, c UNIQUE);
124  CREATE TABLE t6(a UNIQUE, b UNIQUE, c UNIQUE);
125  CREATE TABLE t7(a UNIQUE, b UNIQUE, c UNIQUE);
126  CREATE TABLE t8(a UNIQUE, b UNIQUE, c UNIQUE);
127
128  ROLLBACK;
129}
130
131finish_test
132