tester.tcl 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. # 2001 September 15
  2. #
  3. # The author disclaims copyright to this source code. In place of
  4. # a legal notice, here is a blessing:
  5. #
  6. # 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.
  9. #
  10. #***********************************************************************
  11. # This file implements some common TCL routines used for regression
  12. # testing the SQLite library
  13. #
  14. # $Id: tester.tcl,v 1.22 2002/03/06 22:01:37 drh Exp $
  15. # Make sure tclsqlite was compiled correctly. Abort now with an
  16. # error message if not.
  17. #
  18. if {[sqlite -tcl-uses-utf]} {
  19. if {"\u1234"=="u1234"} {
  20. puts stderr "***** BUILD PROBLEM *****"
  21. puts stderr "$argv0 was linked against an older version"
  22. puts stderr "of TCL that does not support Unicode, but uses a header"
  23. puts stderr "file (\"tcl.h\") from a new TCL version that does support"
  24. puts stderr "Unicode. This combination causes internal errors."
  25. puts stderr "Recompile using a TCL library and header file that match"
  26. puts stderr "and try again.\n**************************"
  27. exit 1
  28. }
  29. } else {
  30. if {"\u1234"!="u1234"} {
  31. puts stderr "***** BUILD PROBLEM *****"
  32. puts stderr "$argv0 was linked against an newer version"
  33. puts stderr "of TCL that supports Unicode, but uses a header file"
  34. puts stderr "(\"tcl.h\") from a old TCL version that does not support"
  35. puts stderr "Unicode. This combination causes internal errors."
  36. puts stderr "Recompile using a TCL library and header file that match"
  37. puts stderr "and try again.\n**************************"
  38. exit 1
  39. }
  40. }
  41. # Create a test database
  42. #
  43. catch {db close}
  44. file delete -force test.db
  45. file delete -force test.db-journal
  46. sqlite db ./test.db
  47. if {[info exists ::SETUP_SQL]} {
  48. db eval $::SETUP_SQL
  49. }
  50. # Abort early if this script has been run before.
  51. #
  52. if {[info exists nTest]} return
  53. # Set the test counters to zero
  54. #
  55. set nErr 0
  56. set nTest 0
  57. set nProb 0
  58. set skip_test 0
  59. set failList {}
  60. # Invoke the do_test procedure to run a single test
  61. #
  62. proc do_test {name cmd expected} {
  63. global argv nErr nTest skip_test
  64. if {$skip_test} {
  65. set skip_test 0
  66. return
  67. }
  68. if {[llength $argv]==0} {
  69. set go 1
  70. } else {
  71. set go 0
  72. foreach pattern $argv {
  73. if {[string match $pattern $name]} {
  74. set go 1
  75. break
  76. }
  77. }
  78. }
  79. if {!$go} return
  80. incr nTest
  81. puts -nonewline $name...
  82. flush stdout
  83. if {[catch {uplevel #0 "$cmd;\n"} result]} {
  84. puts "\nError: $result"
  85. incr nErr
  86. lappend ::failList $name
  87. if {$nErr>10} {puts "*** Giving up..."; finalize_testing}
  88. } elseif {[string compare $result $expected]} {
  89. puts "\nExpected: \[$expected\]\n Got: \[$result\]"
  90. incr nErr
  91. lappend ::failList $name
  92. if {$nErr>10} {puts "*** Giving up..."; finalize_testing}
  93. } else {
  94. puts " Ok"
  95. }
  96. }
  97. # Invoke this procedure on a test that is probabilistic
  98. # and might fail sometimes.
  99. #
  100. proc do_probtest {name cmd expected} {
  101. global argv nProb nTest skip_test
  102. if {$skip_test} {
  103. set skip_test 0
  104. return
  105. }
  106. if {[llength $argv]==0} {
  107. set go 1
  108. } else {
  109. set go 0
  110. foreach pattern $argv {
  111. if {[string match $pattern $name]} {
  112. set go 1
  113. break
  114. }
  115. }
  116. }
  117. if {!$go} return
  118. incr nTest
  119. puts -nonewline $name...
  120. flush stdout
  121. if {[catch {uplevel #0 "$cmd;\n"} result]} {
  122. puts "\nError: $result"
  123. incr nErr
  124. } elseif {[string compare $result $expected]} {
  125. puts "\nExpected: \[$expected\]\n Got: \[$result\]"
  126. puts "NOTE: The results of the previous test depend on system load"
  127. puts "and processor speed. The test may sometimes fail even if the"
  128. puts "library is working correctly."
  129. incr nProb
  130. } else {
  131. puts " Ok"
  132. }
  133. }
  134. # The procedure uses the special "sqlite_malloc_stat" command
  135. # (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
  136. # to see how many malloc()s have not been free()ed. The number
  137. # of surplus malloc()s is stored in the global variable $::Leak.
  138. # If the value in $::Leak grows, it may mean there is a memory leak
  139. # in the library.
  140. #
  141. proc memleak_check {} {
  142. if {[info command sqlite_malloc_stat]!=""} {
  143. set r [sqlite_malloc_stat]
  144. set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
  145. }
  146. }
  147. # Run this routine last
  148. #
  149. proc finish_test {} {
  150. finalize_testing
  151. }
  152. proc finalize_testing {} {
  153. global nTest nErr nProb
  154. if {$nErr==0} memleak_check
  155. catch {db close}
  156. puts "$nErr errors out of $nTest tests"
  157. puts "Failures on these tests: $::failList"
  158. if {$nProb>0} {
  159. puts "$nProb probabilistic tests also failed, but this does"
  160. puts "not necessarily indicate a malfunction."
  161. }
  162. exit [expr {$nErr>0}]
  163. }
  164. # A procedure to execute SQL
  165. #
  166. proc execsql {sql {db db}} {
  167. # puts "SQL = $sql"
  168. return [$db eval $sql]
  169. }
  170. # Execute SQL and catch exceptions.
  171. #
  172. proc catchsql {sql {db db}} {
  173. # puts "SQL = $sql"
  174. set r [catch {$db eval $sql} msg]
  175. lappend r $msg
  176. return $r
  177. }
  178. # Do an VDBE code dump on the SQL given
  179. #
  180. proc explain {sql {db db}} {
  181. puts ""
  182. puts "addr opcode p1 p2 p3 "
  183. puts "---- ------------ ------ ------ ---------------"
  184. $db eval "explain $sql" {} {
  185. puts [format {%-4d %-12.12s %-6d %-6d %s} $addr $opcode $p1 $p2 $p3]
  186. }
  187. }
  188. # Another procedure to execute SQL. This one includes the field
  189. # names in the returned list.
  190. #
  191. proc execsql2 {sql} {
  192. set result {}
  193. db eval $sql data {
  194. foreach f $data(*) {
  195. lappend result $f $data($f)
  196. }
  197. }
  198. return $result
  199. }
  200. # Delete a file or directory
  201. #
  202. proc forcedelete {filename} {
  203. if {[catch {file delete -force $filename}]} {
  204. exec rm -rf $filename
  205. }
  206. }