blob: 3e31ef4ef8a0cba31c2b5874a8849bfb6045a470 [file] [log] [blame]
danielk1977c9cf9012007-05-30 10:36:47 +00001
danielk1977cdc3a6b2007-08-25 13:09:26 +00002ifcapable !memdebug {
3 puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
4 finish_test
5 return
6}
7
danielk1977c9cf9012007-05-30 10:36:47 +00008# Usage: do_malloc_test <test number> <options...>
9#
10# The first argument, <test number>, is an integer used to name the
11# tests executed by this proc. Options are as follows:
12#
13# -tclprep TCL script to run to prepare test.
14# -sqlprep SQL script to run to prepare test.
15# -tclbody TCL script to run with malloc failure simulation.
16# -sqlbody TCL script to run with malloc failure simulation.
17# -cleanup TCL script to run after the test.
18#
19# This command runs a series of tests to verify SQLite's ability
20# to handle an out-of-memory condition gracefully. It is assumed
21# that if this condition occurs a malloc() call will return a
22# NULL pointer. Linux, for example, doesn't do that by default. See
23# the "BUGS" section of malloc(3).
24#
25# Each iteration of a loop, the TCL commands in any argument passed
26# to the -tclbody switch, followed by the SQL commands in any argument
27# passed to the -sqlbody switch are executed. Each iteration the
28# Nth call to sqliteMalloc() is made to fail, where N is increased
29# each time the loop runs starting from 1. When all commands execute
30# successfully, the loop ends.
31#
32proc do_malloc_test {tn args} {
33 array unset ::mallocopts
34 array set ::mallocopts $args
35
36 if {[string is integer $tn]} {
37 set tn malloc-$tn
38 }
drhf3a65f72007-08-22 20:18:21 +000039 if {[info exists ::mallocopts(-start)]} {
40 set start $::mallocopts(-start)
41 } else {
42 set start 1
43 }
danielk1977c9cf9012007-05-30 10:36:47 +000044
45 set ::go 1
drhf3a65f72007-08-22 20:18:21 +000046 for {set ::n $start} {$::go && $::n < 50000} {incr ::n} {
danielk1977c9cf9012007-05-30 10:36:47 +000047 do_test $tn.$::n {
48
49 # Remove all traces of database files test.db and test2.db from the files
50 # system. Then open (empty database) "test.db" with the handle [db].
51 #
danielk1977c9cf9012007-05-30 10:36:47 +000052 catch {db close}
53 catch {file delete -force test.db}
54 catch {file delete -force test.db-journal}
55 catch {file delete -force test2.db}
56 catch {file delete -force test2.db-journal}
drhed138fb2007-08-22 22:04:37 +000057 if {[info exists ::mallocopts(-testdb)]} {
58 file copy $::mallocopts(-testdb) test.db
59 }
danielk1977c9cf9012007-05-30 10:36:47 +000060 catch {sqlite3 db test.db}
danielk1977c9cf9012007-05-30 10:36:47 +000061
62 # Execute any -tclprep and -sqlprep scripts.
63 #
64 if {[info exists ::mallocopts(-tclprep)]} {
65 eval $::mallocopts(-tclprep)
66 }
67 if {[info exists ::mallocopts(-sqlprep)]} {
68 execsql $::mallocopts(-sqlprep)
69 }
70
71 # Now set the ${::n}th malloc() to fail and execute the -tclbody and
72 # -sqlbody scripts.
73 #
drhf3a65f72007-08-22 20:18:21 +000074 sqlite3_memdebug_fail $::n 1
danielk1977c9cf9012007-05-30 10:36:47 +000075 set ::mallocbody {}
76 if {[info exists ::mallocopts(-tclbody)]} {
77 append ::mallocbody "$::mallocopts(-tclbody)\n"
78 }
79 if {[info exists ::mallocopts(-sqlbody)]} {
80 append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
81 }
82 set v [catch $::mallocbody msg]
drhf3a65f72007-08-22 20:18:21 +000083 set failFlag [sqlite3_memdebug_fail -1 0]
84 set go [expr {$failFlag>0}]
danielk1977c9cf9012007-05-30 10:36:47 +000085
danielk1977c9cf9012007-05-30 10:36:47 +000086
drhf3a65f72007-08-22 20:18:21 +000087 if {$failFlag==0} {
danielk1977c9cf9012007-05-30 10:36:47 +000088 if {$v} {
drhf3a65f72007-08-22 20:18:21 +000089 set v2 $msg
danielk1977c9cf9012007-05-30 10:36:47 +000090 } else {
drhf3a65f72007-08-22 20:18:21 +000091 set v 1
92 set v2 1
danielk1977c9cf9012007-05-30 10:36:47 +000093 }
drhf3a65f72007-08-22 20:18:21 +000094 } elseif {!$v} {
95 set v2 $msg
96 } elseif {[info command db]=="" || [db errorcode]==7
97 || $msg=="out of memory"} {
98 set v2 1
danielk1977c9cf9012007-05-30 10:36:47 +000099 } else {
drhf3a65f72007-08-22 20:18:21 +0000100 set v2 $msg
danielk1977c9cf9012007-05-30 10:36:47 +0000101 }
drhf3a65f72007-08-22 20:18:21 +0000102 lappend v $v2
danielk1977c9cf9012007-05-30 10:36:47 +0000103 } {1 1}
104
105 if {[info exists ::mallocopts(-cleanup)]} {
106 catch [list uplevel #0 $::mallocopts(-cleanup)] msg
107 }
108 }
109 unset ::mallocopts
110}