1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-01 06:27:03 +03:00

Improvements to memory leak detection. The --backtrace=NNN option is now

recognized by tester.tcl.  Memory leak summaries are automatically written
to the file ./memleak.txt and each leak is tagged with the test in which
it occurred.  The quick.test script runs on Linux with no errors and
no leaks. (CVS 4273)

FossilOrigin-Name: 21f6b31097692171c6493e6ca6de6acbd62dc595
This commit is contained in:
drh
2007-08-23 02:47:53 +00:00
parent ed138fb3bc
commit 4a50aac564
20 changed files with 212 additions and 108 deletions

View File

@ -10,13 +10,13 @@
#***********************************************************************
# This file runs all tests.
#
# $Id: all.test,v 1.45 2007/08/16 13:01:45 drh Exp $
# $Id: all.test,v 1.46 2007/08/23 02:47:53 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {
memleak_check
# no-op
}
if {[file exists ./sqlite_test_count]} {

View File

@ -12,7 +12,7 @@
# This file contains tests to ensure that the library handles malloc() failures
# correctly. The emphasis in this file is on sqlite3_column_XXX() APIs.
#
# $Id: malloc4.test,v 1.4 2007/08/22 22:04:37 drh Exp $
# $Id: malloc4.test,v 1.5 2007/08/23 02:47:53 drh Exp $
#---------------------------------------------------------------------------
# NOTES ON EXPECTED BEHAVIOUR
@ -69,26 +69,28 @@ proc do_stmt_test {id sql} {
# about explicitly testing them.
#
do_test ${testid}.2.1 {
set mf1 [expr [sqlite3_memdebug_pending] <= 0]
set mf1 [expr [sqlite3_memdebug_pending] < 0]
set ::name8 [sqlite3_column_name $::STMT 0]
set mf2 [expr [sqlite3_memdebug_pending] <= 0]
set mf2 [expr [sqlite3_memdebug_pending] < 0]
expr {$mf1 == $mf2 || $::name8 == ""}
} {1}
do_test ${testid}.2.2 {
set mf1 [expr [sqlite3_memdebug_pending] <= 0]
set mf1 [expr [sqlite3_memdebug_pending] < 0]
btree_breakpoint
set ::name16 [sqlite3_column_name16 $::STMT 0]
set ::name16 [encoding convertfrom unicode $::name16]
set ::name16 [string range $::name16 0 end-1]
set mf2 [expr [sqlite3_memdebug_pending] <= 0]
set mf2 [expr [sqlite3_memdebug_pending] < 0]
puts [list $mf1 $mf2 $::name16]
expr {$mf1 == $mf2 || $::name16 == ""}
} {1}
do_test ${testid}.2.3 {
set mf1 [expr [sqlite3_memdebug_pending] <= 0]
set mf1 [expr [sqlite3_memdebug_pending] < 0]
set ::name8_2 [sqlite3_column_name $::STMT 0]
set mf2 [expr [sqlite3_memdebug_pending] <= 0]
set mf2 [expr [sqlite3_memdebug_pending] < 0]
expr {$mf1 == $mf2 || $::name8_2 == ""}
} {1}
set ::mallocFailed [expr [sqlite3_memdebug_pending] <= 0]
set ::mallocFailed [expr [sqlite3_memdebug_pending] < 0]
do_test ${testid}.2.4 {
expr {
$::name8 == $::name8_2 && $::name16 == $::name8 && !$::mallocFailed ||
@ -113,19 +115,19 @@ proc do_stmt_test {id sql} {
#
do_test ${testid}.4.1 {
set ::text8 [sqlite3_column_text $::STMT 0]
set mf [expr [sqlite3_memdebug_pending] <= 0 && !$::mallocFailed]
set mf [expr [sqlite3_memdebug_pending] < 0 && !$::mallocFailed]
expr {$mf==0 || $::text8 == ""}
} {1}
do_test ${testid}.4.2 {
set ::text16 [sqlite3_column_text16 $::STMT 0]
set ::text16 [encoding convertfrom unicode $::text16]
set ::text16 [string range $::text16 0 end-1]
set mf [expr [sqlite3_memdebug_pending] <= 0 && !$::mallocFailed]
set mf [expr [sqlite3_memdebug_pending] < 0 && !$::mallocFailed]
expr {$mf==0 || $::text16 == ""}
} {1}
do_test ${testid}.4.3 {
set ::text8_2 [sqlite3_column_text $::STMT 0]
set mf [expr [sqlite3_memdebug_pending] <= 0 && !$::mallocFailed]
set mf [expr [sqlite3_memdebug_pending] < 0 && !$::mallocFailed]
expr {$mf==0 || $::text8_2 == "" || ($::text16 == "" && $::text8 != "")}
} {1}
@ -156,7 +158,7 @@ proc do_stmt_test {id sql} {
} {0.0}
set mallocFailedAfterStep [expr \
[sqlite3_memdebug_pending] <= 0 && !$::mallocFailed
[sqlite3_memdebug_pending] < 0 && !$::mallocFailed
]
sqlite3_memdebug_fail -1

View File

@ -6,7 +6,7 @@
#***********************************************************************
# This file runs all tests.
#
# $Id: quick.test,v 1.60 2007/08/16 13:01:45 drh Exp $
# $Id: quick.test,v 1.61 2007/08/23 02:47:54 drh Exp $
proc lshift {lvar} {
upvar $lvar l
@ -55,6 +55,7 @@ set EXCLUDE {
malloc.test
malloc2.test
malloc3.test
malloc4.test
memleak.test
misc7.test
misuse.test

View File

@ -9,7 +9,7 @@
#
#***********************************************************************
#
# $Id: shared2.test,v 1.4 2006/01/26 13:11:37 danielk1977 Exp $
# $Id: shared2.test,v 1.5 2007/08/23 02:47:54 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -124,9 +124,8 @@ db1 close
db2 close
do_test shared2-3.2 {
sqlite3_thread_cleanup
sqlite3_enable_shared_cache 1
} {0}
} {1}
sqlite3_enable_shared_cache $::enable_shared_cache
finish_test

View File

@ -11,7 +11,7 @@
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.86 2007/08/22 22:04:37 drh Exp $
# $Id: tester.tcl,v 1.87 2007/08/23 02:47:54 drh Exp $
# Make sure tclsqlite3 was compiled correctly. Abort now with an
# error message if not.
@ -63,6 +63,21 @@ if {![info exists soft_limit]} {
}
sqlite3_soft_heap_limit $soft_limit
#
# Check the command-line arguments to set the memory debugger
# backtrace depth.
#
# See the sqlite3_memdebug_backtrace() function in mem2.c or
# test_malloc.c for additional information.
#
for {set i 0} {$i<[llength $argv]} {incr i} {
if {[regexp {^--backtrace=(\d+)$} [lindex $argv $i] all value]} {
sqlite3_memdebug_backtrace $value
set argv [lreplace $argv $i $i]
}
}
# Use the pager codec if it is available
#
if {[sqlite3 -has-codec] && [info command sqlite_orig]==""} {
@ -106,7 +121,7 @@ if {![info exists speedTest]} {
#
proc do_test {name cmd expected} {
global argv nErr nTest skip_test maxErr
set ::sqlite_malloc_id $name
sqlite3_memdebug_settitle $name
if {$skip_test} {
set skip_test 0
return
@ -165,20 +180,6 @@ proc speed_trial_summary {name} {
puts [format {%-21.21s %12d uS TOTAL} $name $total_time]
}
# The procedure uses the special "sqlite_malloc_stat" command
# (which is only available if SQLite is compiled with -DSQLITE_DEBUG=1)
# to see how many malloc()s have not been free()ed. The number
# of surplus malloc()s is stored in the global variable $::Leak.
# If the value in $::Leak grows, it may mean there is a memory leak
# in the library.
#
proc memleak_check {} {
if {[info command sqlite_malloc_stat]!=""} {
set r [sqlite_malloc_stat]
set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
}
}
# Run this routine last
#
proc finish_test {} {
@ -186,7 +187,6 @@ proc finish_test {} {
}
proc finalize_testing {} {
global nTest nErr sqlite_open_file_count
if {$nErr==0} memleak_check
catch {db close}
catch {db2 close}
@ -223,6 +223,10 @@ proc finalize_testing {} {
if {[sqlite3_memory_used]>0} {
puts "Unfreed memory: [sqlite3_memory_used] bytes"
incr nErr
ifcapable memdebug {
puts "Writing unfreed memory log to \"./memleak.txt\""
sqlite3_memdebug_dump ./memleak.txt
}
} else {
puts "All memory allocations freed - no leaks"
}