| OLD | NEW |
| 1 # 2001 September 15 | 1 # 2001 September 15 |
| 2 # | 2 # |
| 3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
| 4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
| 5 # | 5 # |
| 6 # May you do good and not evil. | 6 # May you do good and not evil. |
| 7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
| 8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
| 9 # | 9 # |
| 10 #*********************************************************************** | 10 #*********************************************************************** |
| 11 # This file implements some common TCL routines used for regression | 11 # This file implements some common TCL routines used for regression |
| 12 # testing the SQLite library | 12 # testing the SQLite library |
| 13 # | 13 # |
| 14 # $Id: tester.tcl,v 1.143 2009/04/09 01:23:49 drh Exp $ | 14 # $Id: tester.tcl,v 1.143 2009/04/09 01:23:49 drh Exp $ |
| 15 | 15 |
| 16 # | 16 #------------------------------------------------------------------------- |
| 17 # What for user input before continuing. This gives an opportunity | 17 # The commands provided by the code in this file to help with creating |
| 18 # to connect profiling tools to the process. | 18 # test cases are as follows: |
| 19 # | 19 # |
| 20 for {set i 0} {$i<[llength $argv]} {incr i} { | 20 # Commands to manipulate the db and the file-system at a high level: |
| 21 if {[regexp {^-+pause$} [lindex $argv $i] all value]} { | 21 # |
| 22 puts -nonewline "Press RETURN to begin..." | 22 # copy_file FROM TO |
| 23 flush stdout | 23 # drop_all_table ?DB? |
| 24 gets stdin | 24 # forcedelete FILENAME |
| 25 set argv [lreplace $argv $i $i] | 25 # |
| 26 } | 26 # Test the capability of the SQLite version built into the interpreter to |
| 27 } | 27 # determine if a specific test can be run: |
| 28 | 28 # |
| 29 # ifcapable EXPR |
| 30 # |
| 31 # Calulate checksums based on database contents: |
| 32 # |
| 33 # dbcksum DB DBNAME |
| 34 # allcksum ?DB? |
| 35 # cksum ?DB? |
| 36 # |
| 37 # Commands to execute/explain SQL statements: |
| 38 # |
| 39 # stepsql DB SQL |
| 40 # execsql2 SQL |
| 41 # explain_no_trace SQL |
| 42 # explain SQL ?DB? |
| 43 # catchsql SQL ?DB? |
| 44 # execsql SQL ?DB? |
| 45 # |
| 46 # Commands to run test cases: |
| 47 # |
| 48 # do_ioerr_test TESTNAME ARGS... |
| 49 # crashsql ARGS... |
| 50 # integrity_check TESTNAME ?DB? |
| 51 # do_test TESTNAME SCRIPT EXPECTED |
| 52 # do_execsql_test TESTNAME SQL EXPECTED |
| 53 # do_catchsql_test TESTNAME SQL EXPECTED |
| 54 # |
| 55 # Commands providing a lower level interface to the global test counters: |
| 56 # |
| 57 # set_test_counter COUNTER ?VALUE? |
| 58 # omit_test TESTNAME REASON |
| 59 # fail_test TESTNAME |
| 60 # incr_ntest |
| 61 # |
| 62 # Command run at the end of each test file: |
| 63 # |
| 64 # finish_test |
| 65 # |
| 66 # Commands to help create test files that run with the "WAL" and other |
| 67 # permutations (see file permutations.test): |
| 68 # |
| 69 # wal_is_wal_mode |
| 70 # wal_set_journal_mode ?DB? |
| 71 # wal_check_journal_mode TESTNAME?DB? |
| 72 # permutation |
| 73 # presql |
| 74 # |
| 75 |
| 76 # Set the precision of FP arithmatic used by the interpreter. And |
| 77 # configure SQLite to take database file locks on the page that begins |
| 78 # 64KB into the database file instead of the one 1GB in. This means |
| 79 # the code that handles that special case can be tested without creating |
| 80 # very large database files. |
| 81 # |
| 29 set tcl_precision 15 | 82 set tcl_precision 15 |
| 30 sqlite3_test_control_pending_byte 0x0010000 | 83 sqlite3_test_control_pending_byte 0x0010000 |
| 31 | 84 |
| 32 # | 85 |
| 33 # Check the command-line arguments for a default soft-heap-limit. | 86 # If the pager codec is available, create a wrapper for the [sqlite3] |
| 34 # Store this default value in the global variable ::soft_limit and | 87 # command that appends "-key {xyzzy}" to the command line. i.e. this: |
| 35 # update the soft-heap-limit each time this script is run. In that | 88 # |
| 36 # way if an individual test file changes the soft-heap-limit, it | 89 # sqlite3 db test.db |
| 37 # will be reset at the start of the next test file. | 90 # |
| 38 # | 91 # becomes |
| 39 if {![info exists soft_limit]} { | 92 # |
| 40 set soft_limit 0 | 93 # sqlite3 db test.db -key {xyzzy} |
| 41 for {set i 0} {$i<[llength $argv]} {incr i} { | 94 # |
| 42 if {[regexp {^--soft-heap-limit=(.+)$} [lindex $argv $i] all value]} { | 95 if {[info command sqlite_orig]==""} { |
| 43 if {$value!="off"} { | |
| 44 set soft_limit $value | |
| 45 } | |
| 46 set argv [lreplace $argv $i $i] | |
| 47 } | |
| 48 } | |
| 49 } | |
| 50 sqlite3_soft_heap_limit $soft_limit | |
| 51 | |
| 52 # | |
| 53 # Check the command-line arguments to set the memory debugger | |
| 54 # backtrace depth. | |
| 55 # | |
| 56 # See the sqlite3_memdebug_backtrace() function in mem2.c or | |
| 57 # test_malloc.c for additional information. | |
| 58 # | |
| 59 for {set i 0} {$i<[llength $argv]} {incr i} { | |
| 60 if {[lindex $argv $i] eq "--malloctrace"} { | |
| 61 set argv [lreplace $argv $i $i] | |
| 62 sqlite3_memdebug_backtrace 10 | |
| 63 sqlite3_memdebug_log start | |
| 64 set tester_do_malloctrace 1 | |
| 65 } | |
| 66 } | |
| 67 for {set i 0} {$i<[llength $argv]} {incr i} { | |
| 68 if {[regexp {^--backtrace=(\d+)$} [lindex $argv $i] all value]} { | |
| 69 sqlite3_memdebug_backtrace $value | |
| 70 set argv [lreplace $argv $i $i] | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 | |
| 75 proc ostrace_call {zCall nClick zFile i32 i64} { | |
| 76 set s "INSERT INTO ostrace VALUES('$zCall', $nClick, '$zFile', $i32, $i64);" | |
| 77 puts $::ostrace_fd $s | |
| 78 } | |
| 79 | |
| 80 for {set i 0} {$i<[llength $argv]} {incr i} { | |
| 81 if {[lindex $argv $i] eq "--ossummary" || [lindex $argv $i] eq "--ostrace"} { | |
| 82 sqlite3_instvfs create -default ostrace | |
| 83 set tester_do_ostrace 1 | |
| 84 set ostrace_fd [open ostrace.sql w] | |
| 85 puts $ostrace_fd "BEGIN;" | |
| 86 if {[lindex $argv $i] eq "--ostrace"} { | |
| 87 set s "CREATE TABLE ostrace" | |
| 88 append s "(method TEXT, clicks INT, file TEXT, i32 INT, i64 INT);" | |
| 89 puts $ostrace_fd $s | |
| 90 sqlite3_instvfs configure ostrace ostrace_call | |
| 91 sqlite3_instvfs configure ostrace ostrace_call | |
| 92 } | |
| 93 set argv [lreplace $argv $i $i] | |
| 94 } | |
| 95 if {[lindex $argv $i] eq "--binarylog"} { | |
| 96 set tester_do_binarylog 1 | |
| 97 set argv [lreplace $argv $i $i] | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 # | |
| 102 # Check the command-line arguments to set the maximum number of | |
| 103 # errors tolerated before halting. | |
| 104 # | |
| 105 if {![info exists maxErr]} { | |
| 106 set maxErr 1000 | |
| 107 } | |
| 108 for {set i 0} {$i<[llength $argv]} {incr i} { | |
| 109 if {[regexp {^--maxerror=(\d+)$} [lindex $argv $i] all maxErr]} { | |
| 110 set argv [lreplace $argv $i $i] | |
| 111 } | |
| 112 } | |
| 113 #puts "Max error = $maxErr" | |
| 114 | |
| 115 | |
| 116 # Use the pager codec if it is available | |
| 117 # | |
| 118 if {[sqlite3 -has-codec] && [info command sqlite_orig]==""} { | |
| 119 rename sqlite3 sqlite_orig | 96 rename sqlite3 sqlite_orig |
| 120 proc sqlite3 {args} { | 97 proc sqlite3 {args} { |
| 121 if {[llength $args]==2 && [string index [lindex $args 0] 0]!="-"} { | 98 if {[llength $args]>=2 && [string index [lindex $args 0] 0]!="-"} { |
| 122 lappend args -key {xyzzy} | 99 # This command is opening a new database connection. |
| 100 # |
| 101 if {[info exists ::G(perm:sqlite3_args)]} { |
| 102 set args [concat $args $::G(perm:sqlite3_args)] |
| 103 } |
| 104 if {[sqlite_orig -has-codec] && ![info exists ::do_not_use_codec]} { |
| 105 lappend args -key {xyzzy} |
| 106 } |
| 107 |
| 108 set res [uplevel 1 sqlite_orig $args] |
| 109 if {[info exists ::G(perm:presql)]} { |
| 110 [lindex $args 0] eval $::G(perm:presql) |
| 111 } |
| 112 set res |
| 113 } else { |
| 114 # This command is not opening a new database connection. Pass the |
| 115 # arguments through to the C implemenation as the are. |
| 116 # |
| 117 uplevel 1 sqlite_orig $args |
| 123 } | 118 } |
| 124 uplevel 1 sqlite_orig $args | 119 } |
| 125 } | 120 } |
| 126 } | 121 |
| 127 | 122 proc execpresql {handle args} { |
| 128 | 123 trace remove execution $handle enter [list execpresql $handle] |
| 129 # Create a test database | 124 if {[info exists ::G(perm:presql)]} { |
| 130 # | 125 $handle eval $::G(perm:presql) |
| 131 if {![info exists nTest]} { | 126 } |
| 127 } |
| 128 |
| 129 # This command should be called after loading tester.tcl from within |
| 130 # all test scripts that are incompatible with encryption codecs. |
| 131 # |
| 132 proc do_not_use_codec {} { |
| 133 set ::do_not_use_codec 1 |
| 134 reset_db |
| 135 } |
| 136 |
| 137 # The following block only runs the first time this file is sourced. It |
| 138 # does not run in slave interpreters (since the ::cmdlinearg array is |
| 139 # populated before the test script is run in slave interpreters). |
| 140 # |
| 141 if {[info exists cmdlinearg]==0} { |
| 142 |
| 143 # Parse any options specified in the $argv array. This script accepts the |
| 144 # following options: |
| 145 # |
| 146 # --pause |
| 147 # --soft-heap-limit=NN |
| 148 # --maxerror=NN |
| 149 # --malloctrace=N |
| 150 # --backtrace=N |
| 151 # --binarylog=N |
| 152 # --soak=N |
| 153 # |
| 154 set cmdlinearg(soft-heap-limit) 0 |
| 155 set cmdlinearg(maxerror) 1000 |
| 156 set cmdlinearg(malloctrace) 0 |
| 157 set cmdlinearg(backtrace) 10 |
| 158 set cmdlinearg(binarylog) 0 |
| 159 set cmdlinearg(soak) 0 |
| 160 |
| 161 set leftover [list] |
| 162 foreach a $argv { |
| 163 switch -regexp -- $a { |
| 164 {^-+pause$} { |
| 165 # Wait for user input before continuing. This is to give the user an |
| 166 # opportunity to connect profiling tools to the process. |
| 167 puts -nonewline "Press RETURN to begin..." |
| 168 flush stdout |
| 169 gets stdin |
| 170 } |
| 171 {^-+soft-heap-limit=.+$} { |
| 172 foreach {dummy cmdlinearg(soft-heap-limit)} [split $a =] break |
| 173 } |
| 174 {^-+maxerror=.+$} { |
| 175 foreach {dummy cmdlinearg(maxerror)} [split $a =] break |
| 176 } |
| 177 {^-+malloctrace=.+$} { |
| 178 foreach {dummy cmdlinearg(malloctrace)} [split $a =] break |
| 179 if {$cmdlinearg(malloctrace)} { |
| 180 sqlite3_memdebug_log start |
| 181 } |
| 182 } |
| 183 {^-+backtrace=.+$} { |
| 184 foreach {dummy cmdlinearg(backtrace)} [split $a =] break |
| 185 sqlite3_memdebug_backtrace $value |
| 186 } |
| 187 {^-+binarylog=.+$} { |
| 188 foreach {dummy cmdlinearg(binarylog)} [split $a =] break |
| 189 } |
| 190 {^-+soak=.+$} { |
| 191 foreach {dummy cmdlinearg(soak)} [split $a =] break |
| 192 set ::G(issoak) $cmdlinearg(soak) |
| 193 } |
| 194 default { |
| 195 lappend leftover $a |
| 196 } |
| 197 } |
| 198 } |
| 199 set argv $leftover |
| 200 |
| 201 # Install the malloc layer used to inject OOM errors. And the 'automatic' |
| 202 # extensions. This only needs to be done once for the process. |
| 203 # |
| 132 sqlite3_shutdown | 204 sqlite3_shutdown |
| 133 install_malloc_faultsim 1 | 205 install_malloc_faultsim 1 |
| 134 sqlite3_initialize | 206 sqlite3_initialize |
| 135 autoinstall_test_functions | 207 autoinstall_test_functions |
| 136 if {[info exists tester_do_binarylog]} { | 208 |
| 137 sqlite3_instvfs binarylog -default binarylog ostrace.bin | 209 # If the --binarylog option was specified, create the logging VFS. This |
| 138 sqlite3_instvfs marker binarylog "$argv0 $argv" | 210 # call installs the new VFS as the default for all SQLite connections. |
| 139 } | 211 # |
| 140 } | 212 if {$cmdlinearg(binarylog)} { |
| 141 | 213 vfslog new binarylog {} vfslog.bin |
| 214 } |
| 215 |
| 216 # Set the backtrace depth, if malloc tracing is enabled. |
| 217 # |
| 218 if {$cmdlinearg(malloctrace)} { |
| 219 sqlite3_memdebug_backtrace $cmdlinearg(backtrace) |
| 220 } |
| 221 } |
| 222 |
| 223 # Update the soft-heap-limit each time this script is run. In that |
| 224 # way if an individual test file changes the soft-heap-limit, it |
| 225 # will be reset at the start of the next test file. |
| 226 # |
| 227 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) |
| 228 |
| 229 # Create a test database |
| 230 # |
| 142 proc reset_db {} { | 231 proc reset_db {} { |
| 143 catch {db close} | 232 catch {db close} |
| 144 file delete -force test.db | 233 file delete -force test.db |
| 145 file delete -force test.db-journal | 234 file delete -force test.db-journal |
| 235 file delete -force test.db-wal |
| 146 sqlite3 db ./test.db | 236 sqlite3 db ./test.db |
| 147 set ::DB [sqlite3_connection_pointer db] | 237 set ::DB [sqlite3_connection_pointer db] |
| 148 if {[info exists ::SETUP_SQL]} { | 238 if {[info exists ::SETUP_SQL]} { |
| 149 db eval $::SETUP_SQL | 239 db eval $::SETUP_SQL |
| 150 } | 240 } |
| 151 } | 241 } |
| 152 reset_db | 242 reset_db |
| 153 | 243 |
| 154 # Abort early if this script has been run before. | 244 # Abort early if this script has been run before. |
| 155 # | 245 # |
| 156 if {[info exists nTest]} return | 246 if {[info exists TC(count)]} return |
| 157 | 247 |
| 158 # Set the test counters to zero | 248 # Make sure memory statistics are enabled. |
| 159 # | 249 # |
| 160 set nErr 0 | 250 sqlite3_config_memstatus 1 |
| 161 set nTest 0 | 251 |
| 162 set skip_test 0 | 252 # Initialize the test counters and set up commands to access them. |
| 163 set failList {} | 253 # Or, if this is a slave interpreter, set up aliases to write the |
| 164 set omitList {} | 254 # counters in the parent interpreter. |
| 165 if {![info exists speedTest]} { | 255 # |
| 166 set speedTest 0 | 256 if {0==[info exists ::SLAVE]} { |
| 257 set TC(errors) 0 |
| 258 set TC(count) 0 |
| 259 set TC(fail_list) [list] |
| 260 set TC(omit_list) [list] |
| 261 |
| 262 proc set_test_counter {counter args} { |
| 263 if {[llength $args]} { |
| 264 set ::TC($counter) [lindex $args 0] |
| 265 } |
| 266 set ::TC($counter) |
| 267 } |
| 167 } | 268 } |
| 168 | 269 |
| 169 # Record the fact that a sequence of tests were omitted. | 270 # Record the fact that a sequence of tests were omitted. |
| 170 # | 271 # |
| 171 proc omit_test {name reason} { | 272 proc omit_test {name reason} { |
| 172 global omitList | 273 set omitList [set_test_counter omit_list] |
| 173 lappend omitList [list $name $reason] | 274 lappend omitList [list $name $reason] |
| 275 set_test_counter omit_list $omitList |
| 174 } | 276 } |
| 175 | 277 |
| 278 # Record the fact that a test failed. |
| 279 # |
| 280 proc fail_test {name} { |
| 281 set f [set_test_counter fail_list] |
| 282 lappend f $name |
| 283 set_test_counter fail_list $f |
| 284 set_test_counter errors [expr [set_test_counter errors] + 1] |
| 285 |
| 286 set nFail [set_test_counter errors] |
| 287 if {$nFail>=$::cmdlinearg(maxerror)} { |
| 288 puts "*** Giving up..." |
| 289 finalize_testing |
| 290 } |
| 291 } |
| 292 |
| 293 # Increment the number of tests run |
| 294 # |
| 295 proc incr_ntest {} { |
| 296 set_test_counter count [expr [set_test_counter count] + 1] |
| 297 } |
| 298 |
| 299 |
| 176 # Invoke the do_test procedure to run a single test | 300 # Invoke the do_test procedure to run a single test |
| 177 # | 301 # |
| 178 proc do_test {name cmd expected} { | 302 proc do_test {name cmd expected} { |
| 179 global argv nErr nTest skip_test maxErr | 303 |
| 304 global argv cmdlinearg |
| 305 |
| 180 sqlite3_memdebug_settitle $name | 306 sqlite3_memdebug_settitle $name |
| 181 if {[info exists ::tester_do_binarylog]} { | 307 |
| 182 sqlite3_instvfs marker binarylog "Start of $name" | 308 # if {[llength $argv]==0} { |
| 309 # set go 1 |
| 310 # } else { |
| 311 # set go 0 |
| 312 # foreach pattern $argv { |
| 313 # if {[string match $pattern $name]} { |
| 314 # set go 1 |
| 315 # break |
| 316 # } |
| 317 # } |
| 318 # } |
| 319 |
| 320 if {[info exists ::G(perm:prefix)]} { |
| 321 set name "$::G(perm:prefix)$name" |
| 183 } | 322 } |
| 184 if {$skip_test} { | 323 |
| 185 set skip_test 0 | 324 incr_ntest |
| 186 return | |
| 187 } | |
| 188 if {[llength $argv]==0} { | |
| 189 set go 1 | |
| 190 } else { | |
| 191 set go 0 | |
| 192 foreach pattern $argv { | |
| 193 if {[string match $pattern $name]} { | |
| 194 set go 1 | |
| 195 break | |
| 196 } | |
| 197 } | |
| 198 } | |
| 199 if {!$go} return | |
| 200 incr nTest | |
| 201 puts -nonewline $name... | 325 puts -nonewline $name... |
| 202 flush stdout | 326 flush stdout |
| 203 if {[catch {uplevel #0 "$cmd;\n"} result]} { | 327 if {[catch {uplevel #0 "$cmd;\n"} result]} { |
| 204 puts "\nError: $result" | 328 puts "\nError: $result" |
| 205 incr nErr | 329 fail_test $name |
| 206 lappend ::failList $name | |
| 207 if {$nErr>$maxErr} {puts "*** Giving up..."; finalize_testing} | |
| 208 } elseif {[string compare $result $expected]} { | 330 } elseif {[string compare $result $expected]} { |
| 209 puts "\nExpected: \[$expected\]\n Got: \[$result\]" | 331 puts "\nExpected: \[$expected\]\n Got: \[$result\]" |
| 210 incr nErr | 332 fail_test $name |
| 211 lappend ::failList $name | |
| 212 if {$nErr>=$maxErr} {puts "*** Giving up..."; finalize_testing} | |
| 213 } else { | 333 } else { |
| 214 puts " Ok" | 334 puts " Ok" |
| 215 } | 335 } |
| 216 flush stdout | 336 flush stdout |
| 217 if {[info exists ::tester_do_binarylog]} { | 337 } |
| 218 sqlite3_instvfs marker binarylog "End of $name" | 338 |
| 339 proc fix_testname {varname} { |
| 340 upvar $varname testname |
| 341 if {[info exists ::testprefix] |
| 342 && [string is digit [string range $testname 0 0]] |
| 343 } { |
| 344 set testname "${::testprefix}-$testname" |
| 345 } |
| 346 } |
| 347 |
| 348 proc do_execsql_test {testname sql {result {}}} { |
| 349 fix_testname testname |
| 350 uplevel do_test $testname [list "execsql {$sql}"] [list $result] |
| 351 } |
| 352 proc do_catchsql_test {testname sql result} { |
| 353 fix_testname testname |
| 354 uplevel do_test $testname [list "catchsql {$sql}"] [list $result] |
| 355 } |
| 356 |
| 357 #------------------------------------------------------------------------- |
| 358 # Usage: do_select_tests PREFIX ?SWITCHES? TESTLIST |
| 359 # |
| 360 # Where switches are: |
| 361 # |
| 362 # -errorformat FMTSTRING |
| 363 # -count |
| 364 # -query SQL |
| 365 # -tclquery TCL |
| 366 # -repair TCL |
| 367 # |
| 368 proc do_select_tests {prefix args} { |
| 369 |
| 370 set testlist [lindex $args end] |
| 371 set switches [lrange $args 0 end-1] |
| 372 |
| 373 set errfmt "" |
| 374 set countonly 0 |
| 375 set tclquery "" |
| 376 set repair "" |
| 377 |
| 378 for {set i 0} {$i < [llength $switches]} {incr i} { |
| 379 set s [lindex $switches $i] |
| 380 set n [string length $s] |
| 381 if {$n>=2 && [string equal -length $n $s "-query"]} { |
| 382 set tclquery [list execsql [lindex $switches [incr i]]] |
| 383 } elseif {$n>=2 && [string equal -length $n $s "-tclquery"]} { |
| 384 set tclquery [lindex $switches [incr i]] |
| 385 } elseif {$n>=2 && [string equal -length $n $s "-errorformat"]} { |
| 386 set errfmt [lindex $switches [incr i]] |
| 387 } elseif {$n>=2 && [string equal -length $n $s "-repair"]} { |
| 388 set repair [lindex $switches [incr i]] |
| 389 } elseif {$n>=2 && [string equal -length $n $s "-count"]} { |
| 390 set countonly 1 |
| 391 } else { |
| 392 error "unknown switch: $s" |
| 393 } |
| 394 } |
| 395 |
| 396 if {$countonly && $errfmt!=""} { |
| 397 error "Cannot use -count and -errorformat together" |
| 398 } |
| 399 set nTestlist [llength $testlist] |
| 400 if {$nTestlist%3 || $nTestlist==0 } { |
| 401 error "SELECT test list contains [llength $testlist] elements" |
| 402 } |
| 403 |
| 404 eval $repair |
| 405 foreach {tn sql res} $testlist { |
| 406 if {$tclquery != ""} { |
| 407 execsql $sql |
| 408 uplevel do_test ${prefix}.$tn [list $tclquery] [list [list {*}$res]] |
| 409 } elseif {$countonly} { |
| 410 set nRow 0 |
| 411 db eval $sql {incr nRow} |
| 412 uplevel do_test ${prefix}.$tn [list [list set {} $nRow]] [list $res] |
| 413 } elseif {$errfmt==""} { |
| 414 uplevel do_execsql_test ${prefix}.${tn} [list $sql] [list [list {*}$res]] |
| 415 } else { |
| 416 set res [list 1 [string trim [format $errfmt {*}$res]]] |
| 417 uplevel do_catchsql_test ${prefix}.${tn} [list $sql] [list $res] |
| 418 } |
| 419 eval $repair |
| 420 } |
| 421 |
| 422 } |
| 423 |
| 424 proc delete_all_data {} { |
| 425 db eval {SELECT tbl_name AS t FROM sqlite_master WHERE type = 'table'} { |
| 426 db eval "DELETE FROM '[string map {' ''} $t]'" |
| 219 } | 427 } |
| 220 } | 428 } |
| 221 | 429 |
| 222 # Run an SQL script. | 430 # Run an SQL script. |
| 223 # Return the number of microseconds per statement. | 431 # Return the number of microseconds per statement. |
| 224 # | 432 # |
| 225 proc speed_trial {name numstmt units sql} { | 433 proc speed_trial {name numstmt units sql} { |
| 226 puts -nonewline [format {%-21.21s } $name...] | 434 puts -nonewline [format {%-21.21s } $name...] |
| 227 flush stdout | 435 flush stdout |
| 228 set speed [time {sqlite3_exec_nr db $sql}] | 436 set speed [time {sqlite3_exec_nr db $sql}] |
| (...skipping 19 matching lines...) Expand all Loading... |
| 248 set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]] | 456 set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]] |
| 249 } | 457 } |
| 250 set u2 $units/s | 458 set u2 $units/s |
| 251 puts [format {%12d uS %s %s} $tm $rate $u2] | 459 puts [format {%12d uS %s %s} $tm $rate $u2] |
| 252 global total_time | 460 global total_time |
| 253 set total_time [expr {$total_time+$tm}] | 461 set total_time [expr {$total_time+$tm}] |
| 254 } | 462 } |
| 255 proc speed_trial_init {name} { | 463 proc speed_trial_init {name} { |
| 256 global total_time | 464 global total_time |
| 257 set total_time 0 | 465 set total_time 0 |
| 466 sqlite3 versdb :memory: |
| 467 set vers [versdb one {SELECT sqlite_source_id()}] |
| 468 versdb close |
| 469 puts "SQLite $vers" |
| 258 } | 470 } |
| 259 proc speed_trial_summary {name} { | 471 proc speed_trial_summary {name} { |
| 260 global total_time | 472 global total_time |
| 261 puts [format {%-21.21s %12d uS TOTAL} $name $total_time] | 473 puts [format {%-21.21s %12d uS TOTAL} $name $total_time] |
| 262 } | 474 } |
| 263 | 475 |
| 264 # Run this routine last | 476 # Run this routine last |
| 265 # | 477 # |
| 266 proc finish_test {} { | 478 proc finish_test {} { |
| 267 finalize_testing | 479 catch {db close} |
| 480 catch {db2 close} |
| 481 catch {db3 close} |
| 482 if {0==[info exists ::SLAVE]} { finalize_testing } |
| 268 } | 483 } |
| 269 proc finalize_testing {} { | 484 proc finalize_testing {} { |
| 270 global nTest nErr sqlite_open_file_count omitList | 485 global sqlite_open_file_count |
| 486 |
| 487 set omitList [set_test_counter omit_list] |
| 271 | 488 |
| 272 catch {db close} | 489 catch {db close} |
| 273 catch {db2 close} | 490 catch {db2 close} |
| 274 catch {db3 close} | 491 catch {db3 close} |
| 275 | 492 |
| 276 vfs_unlink_test | 493 vfs_unlink_test |
| 277 sqlite3 db {} | 494 sqlite3 db {} |
| 278 # sqlite3_clear_tsd_memdebug | 495 # sqlite3_clear_tsd_memdebug |
| 279 db close | 496 db close |
| 280 sqlite3_reset_auto_extension | 497 sqlite3_reset_auto_extension |
| 281 set heaplimit [sqlite3_soft_heap_limit] | 498 |
| 282 if {$heaplimit!=$::soft_limit} { | |
| 283 puts "soft-heap-limit changed by this script\ | |
| 284 from $::soft_limit to $heaplimit" | |
| 285 } elseif {$heaplimit!="" && $heaplimit>0} { | |
| 286 puts "soft-heap-limit set to $heaplimit" | |
| 287 } | |
| 288 sqlite3_soft_heap_limit 0 | 499 sqlite3_soft_heap_limit 0 |
| 289 incr nTest | 500 set nTest [incr_ntest] |
| 501 set nErr [set_test_counter errors] |
| 502 |
| 290 puts "$nErr errors out of $nTest tests" | 503 puts "$nErr errors out of $nTest tests" |
| 291 if {$nErr>0} { | 504 if {$nErr>0} { |
| 292 puts "Failures on these tests: $::failList" | 505 puts "Failures on these tests: [set_test_counter fail_list]" |
| 293 } | 506 } |
| 294 run_thread_tests 1 | 507 run_thread_tests 1 |
| 295 if {[llength $omitList]>0} { | 508 if {[llength $omitList]>0} { |
| 296 puts "Omitted test cases:" | 509 puts "Omitted test cases:" |
| 297 set prec {} | 510 set prec {} |
| 298 foreach {rec} [lsort $omitList] { | 511 foreach {rec} [lsort $omitList] { |
| 299 if {$rec==$prec} continue | 512 if {$rec==$prec} continue |
| 300 set prec $rec | 513 set prec $rec |
| 301 puts [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]] | 514 puts [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]] |
| 302 } | 515 } |
| 303 } | 516 } |
| 304 if {$nErr>0 && ![working_64bit_int]} { | 517 if {$nErr>0 && ![working_64bit_int]} { |
| 305 puts "******************************************************************" | 518 puts "******************************************************************" |
| 306 puts "N.B.: The version of TCL that you used to build this test harness" | 519 puts "N.B.: The version of TCL that you used to build this test harness" |
| 307 puts "is defective in that it does not support 64-bit integers. Some or" | 520 puts "is defective in that it does not support 64-bit integers. Some or" |
| 308 puts "all of the test failures above might be a result from this defect" | 521 puts "all of the test failures above might be a result from this defect" |
| 309 puts "in your TCL build." | 522 puts "in your TCL build." |
| 310 puts "******************************************************************" | 523 puts "******************************************************************" |
| 311 } | 524 } |
| 312 if {[info exists ::tester_do_binarylog]} { | 525 if {$::cmdlinearg(binarylog)} { |
| 313 sqlite3_instvfs destroy binarylog | 526 vfslog finalize binarylog |
| 314 } | 527 } |
| 315 if {$sqlite_open_file_count} { | 528 if {$sqlite_open_file_count} { |
| 316 puts "$sqlite_open_file_count files were left open" | 529 puts "$sqlite_open_file_count files were left open" |
| 317 incr nErr | 530 incr nErr |
| 318 } | 531 } |
| 319 if {[info exists ::tester_do_ostrace]} { | 532 if {[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]>0 || |
| 320 puts "Writing ostrace.sql..." | 533 [sqlite3_memory_used]>0} { |
| 321 set fd $::ostrace_fd | 534 puts "Unfreed memory: [sqlite3_memory_used] bytes in\ |
| 322 | 535 [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations" |
| 323 puts -nonewline $fd "CREATE TABLE ossummary" | |
| 324 puts $fd "(method TEXT, clicks INTEGER, count INTEGER);" | |
| 325 foreach row [sqlite3_instvfs report ostrace] { | |
| 326 foreach {method count clicks} $row break | |
| 327 puts $fd "INSERT INTO ossummary VALUES('$method', $clicks, $count);" | |
| 328 } | |
| 329 puts $fd "COMMIT;" | |
| 330 close $fd | |
| 331 sqlite3_instvfs destroy ostrace | |
| 332 } | |
| 333 if {[sqlite3_memory_used]>0} { | |
| 334 puts "Unfreed memory: [sqlite3_memory_used] bytes" | |
| 335 incr nErr | 536 incr nErr |
| 336 ifcapable memdebug||mem5||(mem3&&debug) { | 537 ifcapable memdebug||mem5||(mem3&&debug) { |
| 337 puts "Writing unfreed memory log to \"./memleak.txt\"" | 538 puts "Writing unfreed memory log to \"./memleak.txt\"" |
| 338 sqlite3_memdebug_dump ./memleak.txt | 539 sqlite3_memdebug_dump ./memleak.txt |
| 339 } | 540 } |
| 340 } else { | 541 } else { |
| 341 puts "All memory allocations freed - no leaks" | 542 puts "All memory allocations freed - no leaks" |
| 342 ifcapable memdebug||mem5 { | 543 ifcapable memdebug||mem5 { |
| 343 sqlite3_memdebug_dump ./memusage.txt | 544 sqlite3_memdebug_dump ./memusage.txt |
| 344 } | 545 } |
| 345 } | 546 } |
| 346 show_memstats | 547 show_memstats |
| 347 puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes" | 548 puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes" |
| 348 puts "Current memory usage: [sqlite3_memory_highwater] bytes" | 549 puts "Current memory usage: [sqlite3_memory_highwater] bytes" |
| 349 if {[info commands sqlite3_memdebug_malloc_count] ne ""} { | 550 if {[info commands sqlite3_memdebug_malloc_count] ne ""} { |
| 350 puts "Number of malloc() : [sqlite3_memdebug_malloc_count] calls" | 551 puts "Number of malloc() : [sqlite3_memdebug_malloc_count] calls" |
| 351 } | 552 } |
| 352 if {[info exists ::tester_do_malloctrace]} { | 553 if {$::cmdlinearg(malloctrace)} { |
| 353 puts "Writing mallocs.sql..." | 554 puts "Writing mallocs.sql..." |
| 354 memdebug_log_sql | 555 memdebug_log_sql |
| 355 sqlite3_memdebug_log stop | 556 sqlite3_memdebug_log stop |
| 356 sqlite3_memdebug_log clear | 557 sqlite3_memdebug_log clear |
| 357 | 558 |
| 358 if {[sqlite3_memory_used]>0} { | 559 if {[sqlite3_memory_used]>0} { |
| 359 puts "Writing leaks.sql..." | 560 puts "Writing leaks.sql..." |
| 360 sqlite3_memdebug_log sync | 561 sqlite3_memdebug_log sync |
| 361 memdebug_log_sql leaks.sql | 562 memdebug_log_sql leaks.sql |
| 362 } | 563 } |
| 363 } | 564 } |
| 364 foreach f [glob -nocomplain test.db-*-journal] { | 565 foreach f [glob -nocomplain test.db-*-journal] { |
| 365 file delete -force $f | 566 file delete -force $f |
| 366 } | 567 } |
| 367 foreach f [glob -nocomplain test.db-mj*] { | 568 foreach f [glob -nocomplain test.db-mj*] { |
| 368 file delete -force $f | 569 file delete -force $f |
| 369 } | 570 } |
| 370 exit [expr {$nErr>0}] | 571 exit [expr {$nErr>0}] |
| 371 } | 572 } |
| 372 | 573 |
| 373 # Display memory statistics for analysis and debugging purposes. | 574 # Display memory statistics for analysis and debugging purposes. |
| 374 # | 575 # |
| 375 proc show_memstats {} { | 576 proc show_memstats {} { |
| 376 set x [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] | 577 set x [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] |
| 377 set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] | 578 set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] |
| 378 set val [format {now %10d max %10d max-size %10d} \ | 579 set val [format {now %10d max %10d max-size %10d} \ |
| 379 [lindex $x 1] [lindex $x 2] [lindex $y 2]] | 580 [lindex $x 1] [lindex $x 2] [lindex $y 2]] |
| 380 puts "Memory used: $val" | 581 puts "Memory used: $val" |
| 582 set x [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] |
| 583 set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]] |
| 584 puts "Allocation count: $val" |
| 381 set x [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] | 585 set x [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] |
| 382 set y [sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 0] | 586 set y [sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 0] |
| 383 set val [format {now %10d max %10d max-size %10d} \ | 587 set val [format {now %10d max %10d max-size %10d} \ |
| 384 [lindex $x 1] [lindex $x 2] [lindex $y 2]] | 588 [lindex $x 1] [lindex $x 2] [lindex $y 2]] |
| 385 puts "Page-cache used: $val" | 589 puts "Page-cache used: $val" |
| 386 set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] | 590 set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] |
| 387 set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]] | 591 set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]] |
| 388 puts "Page-cache overflow: $val" | 592 puts "Page-cache overflow: $val" |
| 389 set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] | 593 set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] |
| 390 set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]] | 594 set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]] |
| (...skipping 14 matching lines...) Expand all Loading... |
| 405 # | 609 # |
| 406 proc execsql {sql {db db}} { | 610 proc execsql {sql {db db}} { |
| 407 # puts "SQL = $sql" | 611 # puts "SQL = $sql" |
| 408 uplevel [list $db eval $sql] | 612 uplevel [list $db eval $sql] |
| 409 } | 613 } |
| 410 | 614 |
| 411 # Execute SQL and catch exceptions. | 615 # Execute SQL and catch exceptions. |
| 412 # | 616 # |
| 413 proc catchsql {sql {db db}} { | 617 proc catchsql {sql {db db}} { |
| 414 # puts "SQL = $sql" | 618 # puts "SQL = $sql" |
| 415 set r [catch {$db eval $sql} msg] | 619 set r [catch [list uplevel [list $db eval $sql]] msg] |
| 416 lappend r $msg | 620 lappend r $msg |
| 417 return $r | 621 return $r |
| 418 } | 622 } |
| 419 | 623 |
| 420 # Do an VDBE code dump on the SQL given | 624 # Do an VDBE code dump on the SQL given |
| 421 # | 625 # |
| 422 proc explain {sql {db db}} { | 626 proc explain {sql {db db}} { |
| 423 puts "" | 627 puts "" |
| 424 puts "addr opcode p1 p2 p3 p4 p5 #" | 628 puts "addr opcode p1 p2 p3 p4 p5 #" |
| 425 puts "---- ------------ ------ ------ ------ --------------- -- -" | 629 puts "---- ------------ ------ ------ ------ --------------- -- -" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 } | 676 } |
| 473 if {[catch {sqlite3_finalize $vm} errmsg]} { | 677 if {[catch {sqlite3_finalize $vm} errmsg]} { |
| 474 return [list 1 $errmsg] | 678 return [list 1 $errmsg] |
| 475 } | 679 } |
| 476 } | 680 } |
| 477 return $r | 681 return $r |
| 478 } | 682 } |
| 479 | 683 |
| 480 # Delete a file or directory | 684 # Delete a file or directory |
| 481 # | 685 # |
| 482 proc forcedelete {filename} { | 686 proc forcedelete {args} { |
| 483 if {[catch {file delete -force $filename}]} { | 687 foreach filename $args { |
| 484 exec rm -rf $filename | 688 # On windows, sometimes even a [file delete -force] can fail just after |
| 689 # a file is closed. The cause is usually "tag-alongs" - programs like |
| 690 # anti-virus software, automatic backup tools and various explorer |
| 691 # extensions that keep a file open a little longer than we expect, causing |
| 692 # the delete to fail. |
| 693 # |
| 694 # The solution is to wait a short amount of time before retrying the |
| 695 # delete. |
| 696 # |
| 697 set nRetry 50 ;# Maximum number of retries. |
| 698 set nDelay 100 ;# Delay in ms before retrying. |
| 699 for {set i 0} {$i<$nRetry} {incr i} { |
| 700 set rc [catch {file delete -force $filename} msg] |
| 701 if {$rc==0} break |
| 702 after $nDelay |
| 703 } |
| 704 if {$rc} { error $msg } |
| 485 } | 705 } |
| 486 } | 706 } |
| 487 | 707 |
| 488 # Do an integrity check of the entire database | 708 # Do an integrity check of the entire database |
| 489 # | 709 # |
| 490 proc integrity_check {name {db db}} { | 710 proc integrity_check {name {db db}} { |
| 491 ifcapable integrityck { | 711 ifcapable integrityck { |
| 492 do_test $name [list execsql {PRAGMA integrity_check} $db] {ok} | 712 do_test $name [list execsql {PRAGMA integrity_check} $db] {ok} |
| 493 } | 713 } |
| 494 } | 714 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 # | 756 # |
| 537 # The return value is a list of two elements. The first element is a | 757 # The return value is a list of two elements. The first element is a |
| 538 # boolean, indicating whether or not the process actually crashed or | 758 # boolean, indicating whether or not the process actually crashed or |
| 539 # reported some other error. The second element in the returned list is the | 759 # reported some other error. The second element in the returned list is the |
| 540 # error message. This is "child process exited abnormally" if the crash | 760 # error message. This is "child process exited abnormally" if the crash |
| 541 # occured. | 761 # occured. |
| 542 # | 762 # |
| 543 # crashsql -delay CRASHDELAY -file CRASHFILE ?-blocksize BLOCKSIZE? $sql | 763 # crashsql -delay CRASHDELAY -file CRASHFILE ?-blocksize BLOCKSIZE? $sql |
| 544 # | 764 # |
| 545 proc crashsql {args} { | 765 proc crashsql {args} { |
| 546 if {$::tcl_platform(platform)!="unix"} { | |
| 547 error "crashsql should only be used on unix" | |
| 548 } | |
| 549 | 766 |
| 550 set blocksize "" | 767 set blocksize "" |
| 551 set crashdelay 1 | 768 set crashdelay 1 |
| 552 set prngseed 0 | 769 set prngseed 0 |
| 553 set tclbody {} | 770 set tclbody {} |
| 554 set crashfile "" | 771 set crashfile "" |
| 555 set dc "" | 772 set dc "" |
| 556 set sql [lindex $args end] | 773 set sql [lindex $args end] |
| 557 | 774 |
| 558 for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} { | 775 for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} { |
| 559 set z [lindex $args $ii] | 776 set z [lindex $args $ii] |
| 560 set n [string length $z] | 777 set n [string length $z] |
| 561 set z2 [lindex $args [expr $ii+1]] | 778 set z2 [lindex $args [expr $ii+1]] |
| 562 | 779 |
| 563 if {$n>1 && [string first $z -delay]==0} {set crashdelay $z2} \ | 780 if {$n>1 && [string first $z -delay]==0} {set crashdelay $z2} \ |
| 564 elseif {$n>1 && [string first $z -seed]==0} {set prngseed $z2} \ | 781 elseif {$n>1 && [string first $z -seed]==0} {set prngseed $z2} \ |
| 565 elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \ | 782 elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \ |
| 566 elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \ | 783 elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \ |
| 567 elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \ | 784 elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \ |
| 568 elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" }
\ | 785 elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" }
\ |
| 569 else { error "Unrecognized option: $z" } | 786 else { error "Unrecognized option: $z" } |
| 570 } | 787 } |
| 571 | 788 |
| 572 if {$crashfile eq ""} { | 789 if {$crashfile eq ""} { |
| 573 error "Compulsory option -file missing" | 790 error "Compulsory option -file missing" |
| 574 } | 791 } |
| 575 | 792 |
| 576 set cfile [file join [pwd] $crashfile] | 793 # $crashfile gets compared to the native filename in |
| 794 # cfSync(), which can be different then what TCL uses by |
| 795 # default, so here we force it to the "nativename" format. |
| 796 set cfile [string map {\\ \\\\} [file nativename [file join [pwd] $crashfile]]
] |
| 577 | 797 |
| 578 set f [open crash.tcl w] | 798 set f [open crash.tcl w] |
| 579 puts $f "sqlite3_crash_enable 1" | 799 puts $f "sqlite3_crash_enable 1" |
| 580 puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile" | 800 puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile" |
| 581 puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte" | 801 puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte" |
| 582 puts $f "sqlite3 db test.db -vfs crash" | 802 puts $f "sqlite3 db test.db -vfs crash" |
| 583 | 803 |
| 584 # This block sets the cache size of the main database to 10 | 804 # This block sets the cache size of the main database to 10 |
| 585 # pages. This is done in case the build is configured to omit | 805 # pages. This is done in case the build is configured to omit |
| 586 # "PRAGMA cache_size". | 806 # "PRAGMA cache_size". |
| 587 puts $f {db eval {SELECT * FROM sqlite_master;}} | 807 puts $f {db eval {SELECT * FROM sqlite_master;}} |
| 588 puts $f {set bt [btree_from_db db]} | 808 puts $f {set bt [btree_from_db db]} |
| 589 puts $f {btree_set_cache_size $bt 10} | 809 puts $f {btree_set_cache_size $bt 10} |
| 590 if {$prngseed} { | 810 if {$prngseed} { |
| 591 set seed [expr {$prngseed%10007+1}] | 811 set seed [expr {$prngseed%10007+1}] |
| 592 # puts seed=$seed | 812 # puts seed=$seed |
| 593 puts $f "db eval {SELECT randomblob($seed)}" | 813 puts $f "db eval {SELECT randomblob($seed)}" |
| 594 } | 814 } |
| 595 | 815 |
| 596 if {[string length $tclbody]>0} { | 816 if {[string length $tclbody]>0} { |
| 597 puts $f $tclbody | 817 puts $f $tclbody |
| 598 } | 818 } |
| 599 if {[string length $sql]>0} { | 819 if {[string length $sql]>0} { |
| 600 puts $f "db eval {" | 820 puts $f "db eval {" |
| 601 puts $f "$sql" | 821 puts $f "$sql" |
| 602 puts $f "}" | 822 puts $f "}" |
| 603 } | 823 } |
| 604 close $f | 824 close $f |
| 605 | |
| 606 set r [catch { | 825 set r [catch { |
| 607 exec [info nameofexec] crash.tcl >@stdout | 826 exec [info nameofexec] crash.tcl >@stdout |
| 608 } msg] | 827 } msg] |
| 828 |
| 829 # Windows/ActiveState TCL returns a slightly different |
| 830 # error message. We map that to the expected message |
| 831 # so that we don't have to change all of the test |
| 832 # cases. |
| 833 if {$::tcl_platform(platform)=="windows"} { |
| 834 if {$msg=="child killed: unknown signal"} { |
| 835 set msg "child process exited abnormally" |
| 836 } |
| 837 } |
| 838 |
| 609 lappend r $msg | 839 lappend r $msg |
| 610 } | 840 } |
| 611 | 841 |
| 612 # Usage: do_ioerr_test <test number> <options...> | 842 # Usage: do_ioerr_test <test number> <options...> |
| 613 # | 843 # |
| 614 # This proc is used to implement test cases that check that IO errors | 844 # This proc is used to implement test cases that check that IO errors |
| 615 # are correctly handled. The first argument, <test number>, is an integer | 845 # are correctly handled. The first argument, <test number>, is an integer |
| 616 # used to name the tests executed by this proc. Options are as follows: | 846 # used to name the tests executed by this proc. Options are as follows: |
| 617 # | 847 # |
| 618 # -tclprep TCL script to run to prepare test. | 848 # -tclprep TCL script to run to prepare test. |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 set s [expr $::sqlite_io_error_hit==0] | 971 set s [expr $::sqlite_io_error_hit==0] |
| 742 if {$::sqlite_io_error_hit>$::sqlite_io_error_hardhit && $r==0} { | 972 if {$::sqlite_io_error_hit>$::sqlite_io_error_hardhit && $r==0} { |
| 743 set r 1 | 973 set r 1 |
| 744 } | 974 } |
| 745 set ::sqlite_io_error_hit 0 | 975 set ::sqlite_io_error_hit 0 |
| 746 | 976 |
| 747 # One of two things must have happened. either | 977 # One of two things must have happened. either |
| 748 # 1. We never hit the IO error and the SQL returned OK | 978 # 1. We never hit the IO error and the SQL returned OK |
| 749 # 2. An IO error was hit and the SQL failed | 979 # 2. An IO error was hit and the SQL failed |
| 750 # | 980 # |
| 981 #puts "s=$s r=$r q=$q" |
| 751 expr { ($s && !$r && !$q) || (!$s && $r && $q) } | 982 expr { ($s && !$r && !$q) || (!$s && $r && $q) } |
| 752 } {1} | 983 } {1} |
| 753 | 984 |
| 754 set ::sqlite_io_error_hit 0 | 985 set ::sqlite_io_error_hit 0 |
| 755 set ::sqlite_io_error_pending 0 | 986 set ::sqlite_io_error_pending 0 |
| 756 | 987 |
| 757 # Check that no page references were leaked. There should be | 988 # Check that no page references were leaked. There should be |
| 758 # a single reference if there is still an active transaction, | 989 # a single reference if there is still an active transaction, |
| 759 # or zero otherwise. | 990 # or zero otherwise. |
| 760 # | 991 # |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 set f [open $from] | 1182 set f [open $from] |
| 952 fconfigure $f -translation binary | 1183 fconfigure $f -translation binary |
| 953 set t [open $to w] | 1184 set t [open $to w] |
| 954 fconfigure $t -translation binary | 1185 fconfigure $t -translation binary |
| 955 puts -nonewline $t [read $f [file size $from]] | 1186 puts -nonewline $t [read $f [file size $from]] |
| 956 close $t | 1187 close $t |
| 957 close $f | 1188 close $f |
| 958 } | 1189 } |
| 959 } | 1190 } |
| 960 | 1191 |
| 1192 # Drop all tables in database [db] |
| 1193 proc drop_all_tables {{db db}} { |
| 1194 ifcapable trigger&&foreignkey { |
| 1195 set pk [$db one "PRAGMA foreign_keys"] |
| 1196 $db eval "PRAGMA foreign_keys = OFF" |
| 1197 } |
| 1198 foreach {idx name file} [db eval {PRAGMA database_list}] { |
| 1199 if {$idx==1} { |
| 1200 set master sqlite_temp_master |
| 1201 } else { |
| 1202 set master $name.sqlite_master |
| 1203 } |
| 1204 foreach {t type} [$db eval " |
| 1205 SELECT name, type FROM $master |
| 1206 WHERE type IN('table', 'view') AND name NOT LIKE 'sqliteX_%' ESCAPE 'X' |
| 1207 "] { |
| 1208 $db eval "DROP $type \"$t\"" |
| 1209 } |
| 1210 } |
| 1211 ifcapable trigger&&foreignkey { |
| 1212 $db eval "PRAGMA foreign_keys = $pk" |
| 1213 } |
| 1214 } |
| 1215 |
| 1216 #------------------------------------------------------------------------- |
| 1217 # If a test script is executed with global variable $::G(perm:name) set to |
| 1218 # "wal", then the tests are run in WAL mode. Otherwise, they should be run |
| 1219 # in rollback mode. The following Tcl procs are used to make this less |
| 1220 # intrusive: |
| 1221 # |
| 1222 # wal_set_journal_mode ?DB? |
| 1223 # |
| 1224 # If running a WAL test, execute "PRAGMA journal_mode = wal" using |
| 1225 # connection handle DB. Otherwise, this command is a no-op. |
| 1226 # |
| 1227 # wal_check_journal_mode TESTNAME ?DB? |
| 1228 # |
| 1229 # If running a WAL test, execute a tests case that fails if the main |
| 1230 # database for connection handle DB is not currently a WAL database. |
| 1231 # Otherwise (if not running a WAL permutation) this is a no-op. |
| 1232 # |
| 1233 # wal_is_wal_mode |
| 1234 # |
| 1235 # Returns true if this test should be run in WAL mode. False otherwise. |
| 1236 # |
| 1237 proc wal_is_wal_mode {} { |
| 1238 expr {[permutation] eq "wal"} |
| 1239 } |
| 1240 proc wal_set_journal_mode {{db db}} { |
| 1241 if { [wal_is_wal_mode] } { |
| 1242 $db eval "PRAGMA journal_mode = WAL" |
| 1243 } |
| 1244 } |
| 1245 proc wal_check_journal_mode {testname {db db}} { |
| 1246 if { [wal_is_wal_mode] } { |
| 1247 $db eval { SELECT * FROM sqlite_master } |
| 1248 do_test $testname [list $db eval "PRAGMA main.journal_mode"] {wal} |
| 1249 } |
| 1250 } |
| 1251 |
| 1252 proc permutation {} { |
| 1253 set perm "" |
| 1254 catch {set perm $::G(perm:name)} |
| 1255 set perm |
| 1256 } |
| 1257 proc presql {} { |
| 1258 set presql "" |
| 1259 catch {set presql $::G(perm:presql)} |
| 1260 set presql |
| 1261 } |
| 1262 |
| 1263 #------------------------------------------------------------------------- |
| 1264 # |
| 1265 proc slave_test_script {script} { |
| 1266 |
| 1267 # Create the interpreter used to run the test script. |
| 1268 interp create tinterp |
| 1269 |
| 1270 # Populate some global variables that tester.tcl expects to see. |
| 1271 foreach {var value} [list \ |
| 1272 ::argv0 $::argv0 \ |
| 1273 ::argv {} \ |
| 1274 ::SLAVE 1 \ |
| 1275 ] { |
| 1276 interp eval tinterp [list set $var $value] |
| 1277 } |
| 1278 |
| 1279 # The alias used to access the global test counters. |
| 1280 tinterp alias set_test_counter set_test_counter |
| 1281 |
| 1282 # Set up the ::cmdlinearg array in the slave. |
| 1283 interp eval tinterp [list array set ::cmdlinearg [array get ::cmdlinearg]] |
| 1284 |
| 1285 # Set up the ::G array in the slave. |
| 1286 interp eval tinterp [list array set ::G [array get ::G]] |
| 1287 |
| 1288 # Load the various test interfaces implemented in C. |
| 1289 load_testfixture_extensions tinterp |
| 1290 |
| 1291 # Run the test script. |
| 1292 interp eval tinterp $script |
| 1293 |
| 1294 # Check if the interpreter call [run_thread_tests] |
| 1295 if { [interp eval tinterp {info exists ::run_thread_tests_called}] } { |
| 1296 set ::run_thread_tests_called 1 |
| 1297 } |
| 1298 |
| 1299 # Delete the interpreter used to run the test script. |
| 1300 interp delete tinterp |
| 1301 } |
| 1302 |
| 1303 proc slave_test_file {zFile} { |
| 1304 set tail [file tail $zFile] |
| 1305 |
| 1306 # Remember the value of the shared-cache setting. So that it is possible |
| 1307 # to check afterwards that it was not modified by the test script. |
| 1308 # |
| 1309 ifcapable shared_cache { set scs [sqlite3_enable_shared_cache] } |
| 1310 |
| 1311 # Run the test script in a slave interpreter. |
| 1312 # |
| 1313 unset -nocomplain ::run_thread_tests_called |
| 1314 reset_prng_state |
| 1315 set ::sqlite_open_file_count 0 |
| 1316 set time [time { slave_test_script [list source $zFile] }] |
| 1317 set ms [expr [lindex $time 0] / 1000] |
| 1318 |
| 1319 # Test that all files opened by the test script were closed. Omit this |
| 1320 # if the test script has "thread" in its name. The open file counter |
| 1321 # is not thread-safe. |
| 1322 # |
| 1323 if {[info exists ::run_thread_tests_called]==0} { |
| 1324 do_test ${tail}-closeallfiles { expr {$::sqlite_open_file_count>0} } {0} |
| 1325 } |
| 1326 set ::sqlite_open_file_count 0 |
| 1327 |
| 1328 # Test that the global "shared-cache" setting was not altered by |
| 1329 # the test script. |
| 1330 # |
| 1331 ifcapable shared_cache { |
| 1332 set res [expr {[sqlite3_enable_shared_cache] == $scs}] |
| 1333 do_test ${tail}-sharedcachesetting [list set {} $res] 1 |
| 1334 } |
| 1335 |
| 1336 # Add some info to the output. |
| 1337 # |
| 1338 puts "Time: $tail $ms ms" |
| 1339 show_memstats |
| 1340 } |
| 1341 |
| 1342 # Open a new connection on database test.db and execute the SQL script |
| 1343 # supplied as an argument. Before returning, close the new conection and |
| 1344 # restore the 4 byte fields starting at header offsets 28, 92 and 96 |
| 1345 # to the values they held before the SQL was executed. This simulates |
| 1346 # a write by a pre-3.7.0 client. |
| 1347 # |
| 1348 proc sql36231 {sql} { |
| 1349 set B [hexio_read test.db 92 8] |
| 1350 set A [hexio_read test.db 28 4] |
| 1351 sqlite3 db36231 test.db |
| 1352 catch { db36231 func a_string a_string } |
| 1353 execsql $sql db36231 |
| 1354 db36231 close |
| 1355 hexio_write test.db 28 $A |
| 1356 hexio_write test.db 92 $B |
| 1357 return "" |
| 1358 } |
| 1359 |
| 961 # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set | 1360 # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set |
| 962 # to non-zero, then set the global variable $AUTOVACUUM to 1. | 1361 # to non-zero, then set the global variable $AUTOVACUUM to 1. |
| 963 set AUTOVACUUM $sqlite_options(default_autovacuum) | 1362 set AUTOVACUUM $sqlite_options(default_autovacuum) |
| 964 | 1363 |
| 965 source $testdir/thread_common.tcl | 1364 source $testdir/thread_common.tcl |
| OLD | NEW |