blob: a30dad84f22158bc45c66c29425cbdf6859e0b40 [file] [log] [blame]
drhb19a2bc2001-09-16 00:13:26 +00001# 2001 September 15
drh348784e2000-05-29 20:41:49 +00002#
drhb19a2bc2001-09-16 00:13:26 +00003# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
drh348784e2000-05-29 20:41:49 +00005#
drhb19a2bc2001-09-16 00:13:26 +00006# 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.
drh348784e2000-05-29 20:41:49 +00009#
10#***********************************************************************
11# This file implements some common TCL routines used for regression
12# testing the SQLite library
13#
drh04096482001-11-09 22:41:44 +000014# $Id: tester.tcl,v 1.21 2001/11/09 22:41:45 drh Exp $
drhfbc3eab2001-04-06 16:13:42 +000015
16# Make sure tclsqlite was compiled correctly. Abort now with an
17# error message if not.
18#
19if {[sqlite -tcl-uses-utf]} {
20 if {"\u1234"=="u1234"} {
21 puts stderr "***** BUILD PROBLEM *****"
22 puts stderr "$argv0 was linked against an older version"
23 puts stderr "of TCL that does not support Unicode, but uses a header"
24 puts stderr "file (\"tcl.h\") from a new TCL version that does support"
25 puts stderr "Unicode. This combination causes internal errors."
26 puts stderr "Recompile using a TCL library and header file that match"
27 puts stderr "and try again.\n**************************"
28 exit 1
29 }
30} else {
31 if {"\u1234"!="u1234"} {
32 puts stderr "***** BUILD PROBLEM *****"
33 puts stderr "$argv0 was linked against an newer version"
34 puts stderr "of TCL that supports Unicode, but uses a header file"
35 puts stderr "(\"tcl.h\") from a old TCL version that does not support"
36 puts stderr "Unicode. This combination causes internal errors."
37 puts stderr "Recompile using a TCL library and header file that match"
38 puts stderr "and try again.\n**************************"
39 exit 1
40 }
41}
drh348784e2000-05-29 20:41:49 +000042
drhbec2bf42000-05-29 23:48:22 +000043# Create a test database
44#
drh254cba22001-09-20 01:44:42 +000045catch {db close}
46file delete -force test.db
47file delete -force test.db-journal
drh5edc3122001-09-13 21:53:09 +000048sqlite db ./test.db
drhbec2bf42000-05-29 23:48:22 +000049
50# Abort early if this script has been run before.
51#
52if {[info exists nTest]} return
53
54# Set the test counters to zero
55#
drh348784e2000-05-29 20:41:49 +000056set nErr 0
57set nTest 0
drhdb25e382001-03-15 18:21:22 +000058set nProb 0
drh767c2002000-10-19 14:10:08 +000059set skip_test 0
drha1b351a2001-09-14 16:42:12 +000060set failList {}
drh348784e2000-05-29 20:41:49 +000061
62# Invoke the do_test procedure to run a single test
63#
64proc do_test {name cmd expected} {
drh767c2002000-10-19 14:10:08 +000065 global argv nErr nTest skip_test
66 if {$skip_test} {
67 set skip_test 0
68 return
69 }
70 if {[llength $argv]==0} {
drh348784e2000-05-29 20:41:49 +000071 set go 1
72 } else {
73 set go 0
74 foreach pattern $argv {
75 if {[string match $pattern $name]} {
76 set go 1
77 break
78 }
79 }
80 }
81 if {!$go} return
82 incr nTest
drh5edc3122001-09-13 21:53:09 +000083 puts -nonewline $name...
drh348784e2000-05-29 20:41:49 +000084 flush stdout
85 if {[catch {uplevel #0 "$cmd;\n"} result]} {
86 puts "\nError: $result"
87 incr nErr
drha1b351a2001-09-14 16:42:12 +000088 lappend ::failList $name
89 if {$nErr>10} {puts "*** Giving up..."; finalize_testing}
drh348784e2000-05-29 20:41:49 +000090 } elseif {[string compare $result $expected]} {
91 puts "\nExpected: \[$expected\]\n Got: \[$result\]"
92 incr nErr
drha1b351a2001-09-14 16:42:12 +000093 lappend ::failList $name
94 if {$nErr>10} {puts "*** Giving up..."; finalize_testing}
drh348784e2000-05-29 20:41:49 +000095 } else {
96 puts " Ok"
97 }
98}
99
drhdb25e382001-03-15 18:21:22 +0000100# Invoke this procedure on a test that is probabilistic
101# and might fail sometimes.
102#
103proc do_probtest {name cmd expected} {
104 global argv nProb nTest skip_test
105 if {$skip_test} {
106 set skip_test 0
107 return
108 }
109 if {[llength $argv]==0} {
110 set go 1
111 } else {
112 set go 0
113 foreach pattern $argv {
114 if {[string match $pattern $name]} {
115 set go 1
116 break
117 }
118 }
119 }
120 if {!$go} return
121 incr nTest
drh5edc3122001-09-13 21:53:09 +0000122 puts -nonewline $name...
drhdb25e382001-03-15 18:21:22 +0000123 flush stdout
124 if {[catch {uplevel #0 "$cmd;\n"} result]} {
125 puts "\nError: $result"
126 incr nErr
127 } elseif {[string compare $result $expected]} {
128 puts "\nExpected: \[$expected\]\n Got: \[$result\]"
129 puts "NOTE: The results of the previous test depend on system load"
130 puts "and processor speed. The test may sometimes fail even if the"
131 puts "library is working correctly."
132 incr nProb
133 } else {
134 puts " Ok"
135 }
136}
137
drhdaffd0e2001-04-11 14:28:42 +0000138# The procedure uses the special "sqlite_malloc_stat" command
drh8c82b352000-12-10 18:23:50 +0000139# (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
140# to see how many malloc()s have not been free()ed. The number
141# of surplus malloc()s is stored in the global variable $::Leak.
142# If the value in $::Leak grows, it may mean there is a memory leak
143# in the library.
144#
145proc memleak_check {} {
drhdaffd0e2001-04-11 14:28:42 +0000146 if {[info command sqlite_malloc_stat]!=""} {
147 set r [sqlite_malloc_stat]
148 set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
149 }
drh8c82b352000-12-10 18:23:50 +0000150}
151
drh348784e2000-05-29 20:41:49 +0000152# Run this routine last
153#
154proc finish_test {} {
drha1b351a2001-09-14 16:42:12 +0000155 finalize_testing
156}
157proc finalize_testing {} {
drhdb25e382001-03-15 18:21:22 +0000158 global nTest nErr nProb
drha1b351a2001-09-14 16:42:12 +0000159 if {$nErr==0} memleak_check
drh6e142f52000-06-08 13:36:40 +0000160 catch {db close}
drh348784e2000-05-29 20:41:49 +0000161 puts "$nErr errors out of $nTest tests"
drha1b351a2001-09-14 16:42:12 +0000162 puts "Failures on these tests: $::failList"
drhdb25e382001-03-15 18:21:22 +0000163 if {$nProb>0} {
164 puts "$nProb probabilistic tests also failed, but this does"
165 puts "not necessarily indicate a malfunction."
166 }
167 exit [expr {$nErr>0}]
drh348784e2000-05-29 20:41:49 +0000168}
169
drh348784e2000-05-29 20:41:49 +0000170# A procedure to execute SQL
171#
drhc4a3c772001-04-04 11:48:57 +0000172proc execsql {sql {db db}} {
drhacbcdc42001-01-22 00:31:53 +0000173 # puts "SQL = $sql"
drhc4a3c772001-04-04 11:48:57 +0000174 return [$db eval $sql]
drh348784e2000-05-29 20:41:49 +0000175}
drh3aadb2e2000-05-31 17:59:25 +0000176
drhadbca9c2001-09-27 15:11:53 +0000177# Execute SQL and catch exceptions.
178#
179proc catchsql {sql {db db}} {
180 # puts "SQL = $sql"
181 set r [catch {$db eval $sql} msg]
182 lappend r $msg
183 return $r
184}
185
drh04096482001-11-09 22:41:44 +0000186# Do an VDBE code dump on the SQL given
187#
188proc explain {sql {db db}} {
189 puts ""
190 puts "addr opcode p1 p2 p3 "
191 puts "---- ------------ ------ ------ ---------------"
192 $db eval "explain $sql" {} {
193 puts [format {%-4d %-12.12s %-6d %-6d %s} $addr $opcode $p1 $p2 $p3]
194 }
195}
196
drh3aadb2e2000-05-31 17:59:25 +0000197# Another procedure to execute SQL. This one includes the field
198# names in the returned list.
199#
200proc execsql2 {sql} {
201 set result {}
202 db eval $sql data {
203 foreach f $data(*) {
204 lappend result $f $data($f)
205 }
206 }
207 return $result
208}
drh17a68932001-01-31 13:28:08 +0000209
210# Delete a file or directory
211#
212proc forcedelete {filename} {
213 if {[catch {file delete -force $filename}]} {
214 exec rm -rf $filename
215 }
216}