import less(1)
[unleashed/tickless.git] / usr / src / lib / libsqlite / test / tester.tcl
blob8cc6951eee27be079536ff5862225a66dfc3d1dc
2 #pragma ident "%Z%%M% %I% %E% SMI"
4 # 2001 September 15
6 # The author disclaims copyright to this source code. In place of
7 # a legal notice, here is a blessing:
9 # May you do good and not evil.
10 # May you find forgiveness for yourself and forgive others.
11 # May you share freely, never taking more than you give.
13 #***********************************************************************
14 # This file implements some common TCL routines used for regression
15 # testing the SQLite library
17 # $Id: tester.tcl,v 1.28 2004/02/14 01:39:50 drh Exp $
19 # Make sure tclsqlite was compiled correctly. Abort now with an
20 # error message if not.
22 if {[sqlite -tcl-uses-utf]} {
23 if {"\u1234"=="u1234"} {
24 puts stderr "***** BUILD PROBLEM *****"
25 puts stderr "$argv0 was linked against an older version"
26 puts stderr "of TCL that does not support Unicode, but uses a header"
27 puts stderr "file (\"tcl.h\") from a new TCL version that does support"
28 puts stderr "Unicode. This combination causes internal errors."
29 puts stderr "Recompile using a TCL library and header file that match"
30 puts stderr "and try again.\n**************************"
31 exit 1
33 } else {
34 if {"\u1234"!="u1234"} {
35 puts stderr "***** BUILD PROBLEM *****"
36 puts stderr "$argv0 was linked against an newer version"
37 puts stderr "of TCL that supports Unicode, but uses a header file"
38 puts stderr "(\"tcl.h\") from a old TCL version that does not support"
39 puts stderr "Unicode. This combination causes internal errors."
40 puts stderr "Recompile using a TCL library and header file that match"
41 puts stderr "and try again.\n**************************"
42 exit 1
46 # Use the pager codec if it is available
48 if {[sqlite -has-codec] && [info command sqlite_orig]==""} {
49 rename sqlite sqlite_orig
50 proc sqlite {args} {
51 if {[llength $args]==2 && [string index [lindex $args 0] 0]!="-"} {
52 lappend args -key {xyzzy}
54 uplevel 1 sqlite_orig $args
59 # Create a test database
61 catch {db close}
62 file delete -force test.db
63 file delete -force test.db-journal
64 sqlite db ./test.db
65 if {[info exists ::SETUP_SQL]} {
66 db eval $::SETUP_SQL
69 # Abort early if this script has been run before.
71 if {[info exists nTest]} return
73 # Set the test counters to zero
75 set nErr 0
76 set nTest 0
77 set nProb 0
78 set skip_test 0
79 set failList {}
81 # Invoke the do_test procedure to run a single test
83 proc do_test {name cmd expected} {
84 global argv nErr nTest skip_test
85 if {$skip_test} {
86 set skip_test 0
87 return
89 if {[llength $argv]==0} {
90 set go 1
91 } else {
92 set go 0
93 foreach pattern $argv {
94 if {[string match $pattern $name]} {
95 set go 1
96 break
100 if {!$go} return
101 incr nTest
102 puts -nonewline $name...
103 flush stdout
104 if {[catch {uplevel #0 "$cmd;\n"} result]} {
105 puts "\nError: $result"
106 incr nErr
107 lappend ::failList $name
108 if {$nErr>100} {puts "*** Giving up..."; finalize_testing}
109 } elseif {[string compare $result $expected]} {
110 puts "\nExpected: \[$expected\]\n Got: \[$result\]"
111 incr nErr
112 lappend ::failList $name
113 if {$nErr>100} {puts "*** Giving up..."; finalize_testing}
114 } else {
115 puts " Ok"
119 # Invoke this procedure on a test that is probabilistic
120 # and might fail sometimes.
122 proc do_probtest {name cmd expected} {
123 global argv nProb nTest skip_test
124 if {$skip_test} {
125 set skip_test 0
126 return
128 if {[llength $argv]==0} {
129 set go 1
130 } else {
131 set go 0
132 foreach pattern $argv {
133 if {[string match $pattern $name]} {
134 set go 1
135 break
139 if {!$go} return
140 incr nTest
141 puts -nonewline $name...
142 flush stdout
143 if {[catch {uplevel #0 "$cmd;\n"} result]} {
144 puts "\nError: $result"
145 incr nErr
146 } elseif {[string compare $result $expected]} {
147 puts "\nExpected: \[$expected\]\n Got: \[$result\]"
148 puts "NOTE: The results of the previous test depend on system load"
149 puts "and processor speed. The test may sometimes fail even if the"
150 puts "library is working correctly."
151 incr nProb
152 } else {
153 puts " Ok"
157 # The procedure uses the special "sqlite_malloc_stat" command
158 # (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
159 # to see how many malloc()s have not been free()ed. The number
160 # of surplus malloc()s is stored in the global variable $::Leak.
161 # If the value in $::Leak grows, it may mean there is a memory leak
162 # in the library.
164 proc memleak_check {} {
165 if {[info command sqlite_malloc_stat]!=""} {
166 set r [sqlite_malloc_stat]
167 set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
171 # Run this routine last
173 proc finish_test {} {
174 finalize_testing
176 proc finalize_testing {} {
177 global nTest nErr nProb sqlite_open_file_count
178 if {$nErr==0} memleak_check
179 catch {db close}
180 puts "$nErr errors out of $nTest tests"
181 puts "Failures on these tests: $::failList"
182 if {$nProb>0} {
183 puts "$nProb probabilistic tests also failed, but this does"
184 puts "not necessarily indicate a malfunction."
186 if {$sqlite_open_file_count} {
187 puts "$sqlite_open_file_count files were left open"
188 incr nErr
190 exit [expr {$nErr>0}]
193 # A procedure to execute SQL
195 proc execsql {sql {db db}} {
196 # puts "SQL = $sql"
197 return [$db eval $sql]
200 # Execute SQL and catch exceptions.
202 proc catchsql {sql {db db}} {
203 # puts "SQL = $sql"
204 set r [catch {$db eval $sql} msg]
205 lappend r $msg
206 return $r
209 # Do an VDBE code dump on the SQL given
211 proc explain {sql {db db}} {
212 puts ""
213 puts "addr opcode p1 p2 p3 "
214 puts "---- ------------ ------ ------ ---------------"
215 $db eval "explain $sql" {} {
216 puts [format {%-4d %-12.12s %-6d %-6d %s} $addr $opcode $p1 $p2 $p3]
220 # Another procedure to execute SQL. This one includes the field
221 # names in the returned list.
223 proc execsql2 {sql} {
224 set result {}
225 db eval $sql data {
226 foreach f $data(*) {
227 lappend result $f $data($f)
230 return $result
233 # Use the non-callback API to execute multiple SQL statements
235 proc stepsql {dbptr sql} {
236 set sql [string trim $sql]
237 set r 0
238 while {[string length $sql]>0} {
239 if {[catch {sqlite_compile $dbptr $sql sqltail} vm]} {
240 return [list 1 $vm]
242 set sql [string trim $sqltail]
243 while {[sqlite_step $vm N VAL COL]=="SQLITE_ROW"} {
244 foreach v $VAL {lappend r $v}
246 if {[catch {sqlite_finalize $vm} errmsg]} {
247 return [list 1 $errmsg]
250 return $r
253 # Delete a file or directory
255 proc forcedelete {filename} {
256 if {[catch {file delete -force $filename}]} {
257 exec rm -rf $filename
261 # Do an integrity check of the entire database
263 proc integrity_check {name} {
264 do_test $name {
265 execsql {PRAGMA integrity_check}
266 } {ok}