blob: 9c86030ea0ec029a6b7b8327c999133178a8d7fc [file] [log] [blame]
drh348784e2000-05-29 20:41:49 +00001# Copyright (c) 1999, 2000 D. Richard Hipp
2#
3# This program is free software; you can redistribute it and/or
4# modify it under the terms of the GNU General Public
5# License as published by the Free Software Foundation; either
6# version 2 of the License, or (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11# General Public License for more details.
12#
13# You should have received a copy of the GNU General Public
14# License along with this library; if not, write to the
15# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16# Boston, MA 02111-1307, USA.
17#
18# Author contact information:
19# drh@hwaci.com
20# http://www.hwaci.com/drh/
21#
22#***********************************************************************
23# This file implements some common TCL routines used for regression
24# testing the SQLite library
25#
drhfbc3eab2001-04-06 16:13:42 +000026# $Id: tester.tcl,v 1.14 2001/04/06 16:13:43 drh Exp $
27
28# Make sure tclsqlite was compiled correctly. Abort now with an
29# error message if not.
30#
31if {[sqlite -tcl-uses-utf]} {
32 if {"\u1234"=="u1234"} {
33 puts stderr "***** BUILD PROBLEM *****"
34 puts stderr "$argv0 was linked against an older version"
35 puts stderr "of TCL that does not support Unicode, but uses a header"
36 puts stderr "file (\"tcl.h\") from a new TCL version that does support"
37 puts stderr "Unicode. This combination causes internal errors."
38 puts stderr "Recompile using a TCL library and header file that match"
39 puts stderr "and try again.\n**************************"
40 exit 1
41 }
42} else {
43 if {"\u1234"!="u1234"} {
44 puts stderr "***** BUILD PROBLEM *****"
45 puts stderr "$argv0 was linked against an newer version"
46 puts stderr "of TCL that supports Unicode, but uses a header file"
47 puts stderr "(\"tcl.h\") from a old TCL version that does not support"
48 puts stderr "Unicode. This combination causes internal errors."
49 puts stderr "Recompile using a TCL library and header file that match"
50 puts stderr "and try again.\n**************************"
51 exit 1
52 }
53}
drh348784e2000-05-29 20:41:49 +000054
drhbec2bf42000-05-29 23:48:22 +000055# Create a test database
56#
drh767c2002000-10-19 14:10:08 +000057if {![info exists dbprefix]} {
58 if {[info exists env(SQLITE_PREFIX)]} {
59 set dbprefix $env(SQLITE_PREFIX):
60 } else {
61 set dbprefix "gdbm:"
62 }
63}
64switch $dbprefix {
65 gdbm: {
drh3494ffe2001-03-20 12:55:13 +000066 foreach f [glob -nocomplain testdb/*] {
67 catch {file delete -force $f}
68 }
drh17a68932001-01-31 13:28:08 +000069 if {[catch {file delete -force testdb}]} {
70 exec rm -rf testdb
71 }
drh767c2002000-10-19 14:10:08 +000072 file mkdir testdb
73 }
74 memory: {
75 # do nothing
76 }
77}
78sqlite db ${dbprefix}testdb
drhbec2bf42000-05-29 23:48:22 +000079
80# Abort early if this script has been run before.
81#
82if {[info exists nTest]} return
83
84# Set the test counters to zero
85#
drh348784e2000-05-29 20:41:49 +000086set nErr 0
87set nTest 0
drhdb25e382001-03-15 18:21:22 +000088set nProb 0
drh767c2002000-10-19 14:10:08 +000089set skip_test 0
drh348784e2000-05-29 20:41:49 +000090
91# Invoke the do_test procedure to run a single test
92#
93proc do_test {name cmd expected} {
drh767c2002000-10-19 14:10:08 +000094 global argv nErr nTest skip_test
95 if {$skip_test} {
96 set skip_test 0
97 return
98 }
99 if {[llength $argv]==0} {
drh348784e2000-05-29 20:41:49 +0000100 set go 1
101 } else {
102 set go 0
103 foreach pattern $argv {
104 if {[string match $pattern $name]} {
105 set go 1
106 break
107 }
108 }
109 }
110 if {!$go} return
111 incr nTest
drh767c2002000-10-19 14:10:08 +0000112 puts -nonewline $::dbprefix$name...
drh348784e2000-05-29 20:41:49 +0000113 flush stdout
114 if {[catch {uplevel #0 "$cmd;\n"} result]} {
115 puts "\nError: $result"
116 incr nErr
117 } elseif {[string compare $result $expected]} {
118 puts "\nExpected: \[$expected\]\n Got: \[$result\]"
119 incr nErr
120 } else {
121 puts " Ok"
122 }
123}
124
drhdb25e382001-03-15 18:21:22 +0000125# Invoke this procedure on a test that is probabilistic
126# and might fail sometimes.
127#
128proc do_probtest {name cmd expected} {
129 global argv nProb nTest skip_test
130 if {$skip_test} {
131 set skip_test 0
132 return
133 }
134 if {[llength $argv]==0} {
135 set go 1
136 } else {
137 set go 0
138 foreach pattern $argv {
139 if {[string match $pattern $name]} {
140 set go 1
141 break
142 }
143 }
144 }
145 if {!$go} return
146 incr nTest
147 puts -nonewline $::dbprefix$name...
148 flush stdout
149 if {[catch {uplevel #0 "$cmd;\n"} result]} {
150 puts "\nError: $result"
151 incr nErr
152 } elseif {[string compare $result $expected]} {
153 puts "\nExpected: \[$expected\]\n Got: \[$result\]"
154 puts "NOTE: The results of the previous test depend on system load"
155 puts "and processor speed. The test may sometimes fail even if the"
156 puts "library is working correctly."
157 incr nProb
158 } else {
159 puts " Ok"
160 }
161}
162
drh767c2002000-10-19 14:10:08 +0000163# Skip a test based on the dbprefix
164#
165proc skipif {args} {
166 foreach a $args {
167 if {$::dbprefix==$a} {
168 set ::skip_test 1
169 return
170 }
171 }
172}
173
174# Run the next test only if the dbprefix is among the listed arguments
175#
176proc testif {args} {
177 foreach a $args {
178 if {$::dbprefix==$a} {
179 set ::skip_test 0
180 return
181 }
182 }
183 set ::skip_test 1
184}
185
drh8c82b352000-12-10 18:23:50 +0000186# The procedure uses the special "--malloc-stats--" macro of SQLite
187# (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
188# to see how many malloc()s have not been free()ed. The number
189# of surplus malloc()s is stored in the global variable $::Leak.
190# If the value in $::Leak grows, it may mean there is a memory leak
191# in the library.
192#
193proc memleak_check {} {
194 set r [execsql {--malloc-stats--}]
195 if {$r==""} return
196 set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
197 # puts "*** $::Leak mallocs have not been freed ***"
198}
199
drh348784e2000-05-29 20:41:49 +0000200# Run this routine last
201#
202proc finish_test {} {
drhdb25e382001-03-15 18:21:22 +0000203 global nTest nErr nProb
drh8c82b352000-12-10 18:23:50 +0000204 memleak_check
drh6e142f52000-06-08 13:36:40 +0000205 catch {db close}
drh348784e2000-05-29 20:41:49 +0000206 puts "$nErr errors out of $nTest tests"
drhdb25e382001-03-15 18:21:22 +0000207 if {$nProb>0} {
208 puts "$nProb probabilistic tests also failed, but this does"
209 puts "not necessarily indicate a malfunction."
210 }
211 exit [expr {$nErr>0}]
drh348784e2000-05-29 20:41:49 +0000212}
213
drh348784e2000-05-29 20:41:49 +0000214# A procedure to execute SQL
215#
drhc4a3c772001-04-04 11:48:57 +0000216proc execsql {sql {db db}} {
drhacbcdc42001-01-22 00:31:53 +0000217 # puts "SQL = $sql"
drhc4a3c772001-04-04 11:48:57 +0000218 return [$db eval $sql]
drh348784e2000-05-29 20:41:49 +0000219}
drh3aadb2e2000-05-31 17:59:25 +0000220
221# Another procedure to execute SQL. This one includes the field
222# names in the returned list.
223#
224proc execsql2 {sql} {
225 set result {}
226 db eval $sql data {
227 foreach f $data(*) {
228 lappend result $f $data($f)
229 }
230 }
231 return $result
232}
drh17a68932001-01-31 13:28:08 +0000233
234# Delete a file or directory
235#
236proc forcedelete {filename} {
237 if {[catch {file delete -force $filename}]} {
238 exec rm -rf $filename
239 }
240}