blob: 432bddf3cc1828f7258e59de8fa0fe44eb8d1de0 [file] [log] [blame]
drhb3226e82007-08-13 12:39:03 +00001# 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#
danielk1977a1644fd2007-08-29 12:31:25 +000015# $Id: mallocC.test,v 1.4 2007/08/29 12:31:29 danielk1977 Exp $
drhb3226e82007-08-13 12:39:03 +000016
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20# Only run these tests if memory debugging is turned on.
21#
drhed138fb2007-08-22 22:04:37 +000022ifcapable !memdebug {
23 puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
24 finish_test
25 return
drhb3226e82007-08-13 12:39:03 +000026}
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.
danielk1977a1644fd2007-08-29 12:31:25 +000064 sqlite3_memdebug_fail $::n -repeat 1
drhb4035742007-08-13 12:58:18 +000065 do_test mallocC-$tn.$::n.1 {
drhb3226e82007-08-13 12:39:03 +000066 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.
danielk1977a1644fd2007-08-29 12:31:25 +000079 set nFail [sqlite3_memdebug_fail -1]
drhed138fb2007-08-22 22:04:37 +000080 if {$nFail==0} {
drhb3226e82007-08-13 12:39:03 +000081 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.
drhb4035742007-08-13 12:58:18 +000090 do_test mallocC-$tn.$::n.2 {
drhb3226e82007-08-13 12:39:03 +000091 catch {
92 execsql {
93 ROLLBACK;
94 }
95 }
96 expr 0
97 } {0}
98
99 # Checksum the database.
drhb4035742007-08-13 12:58:18 +0000100 #do_test mallocC-$tn.$::n.3 {
drhb3226e82007-08-13 12:39:03 +0000101 # cksum db
102 #} $sum
103
drhb4035742007-08-13 12:58:18 +0000104 #integrity_check mallocC-$tn.$::n.4
drhb3226e82007-08-13 12:39:03 +0000105 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