Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: third_party/sqlite/src/test/tester.tcl

Issue 901033002: Import SQLite 3.8.7.4. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Chromium changes to support SQLite 3.8.7.4. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 # The commands provided by the code in this file to help with creating 17 # The commands provided by the code in this file to help with creating
18 # test cases are as follows: 18 # test cases are as follows:
19 # 19 #
20 # Commands to manipulate the db and the file-system at a high level: 20 # Commands to manipulate the db and the file-system at a high level:
21 # 21 #
22 # is_relative_file
23 # test_pwd
24 # get_pwd
22 # copy_file FROM TO 25 # copy_file FROM TO
23 # drop_all_table ?DB? 26 # delete_file FILENAME
27 # drop_all_tables ?DB?
28 # forcecopy FROM TO
24 # forcedelete FILENAME 29 # forcedelete FILENAME
25 # 30 #
26 # Test the capability of the SQLite version built into the interpreter to 31 # Test the capability of the SQLite version built into the interpreter to
27 # determine if a specific test can be run: 32 # determine if a specific test can be run:
28 # 33 #
34 # capable EXPR
29 # ifcapable EXPR 35 # ifcapable EXPR
30 # 36 #
31 # Calulate checksums based on database contents: 37 # Calulate checksums based on database contents:
32 # 38 #
33 # dbcksum DB DBNAME 39 # dbcksum DB DBNAME
34 # allcksum ?DB? 40 # allcksum ?DB?
35 # cksum ?DB? 41 # cksum ?DB?
36 # 42 #
37 # Commands to execute/explain SQL statements: 43 # Commands to execute/explain SQL statements:
38 # 44 #
45 # memdbsql SQL
39 # stepsql DB SQL 46 # stepsql DB SQL
40 # execsql2 SQL 47 # execsql2 SQL
41 # explain_no_trace SQL 48 # explain_no_trace SQL
42 # explain SQL ?DB? 49 # explain SQL ?DB?
43 # catchsql SQL ?DB? 50 # catchsql SQL ?DB?
44 # execsql SQL ?DB? 51 # execsql SQL ?DB?
45 # 52 #
46 # Commands to run test cases: 53 # Commands to run test cases:
47 # 54 #
48 # do_ioerr_test TESTNAME ARGS... 55 # do_ioerr_test TESTNAME ARGS...
49 # crashsql ARGS... 56 # crashsql ARGS...
50 # integrity_check TESTNAME ?DB? 57 # integrity_check TESTNAME ?DB?
58 # verify_ex_errcode TESTNAME EXPECTED ?DB?
51 # do_test TESTNAME SCRIPT EXPECTED 59 # do_test TESTNAME SCRIPT EXPECTED
52 # do_execsql_test TESTNAME SQL EXPECTED 60 # do_execsql_test TESTNAME SQL EXPECTED
53 # do_catchsql_test TESTNAME SQL EXPECTED 61 # do_catchsql_test TESTNAME SQL EXPECTED
62 # do_timed_execsql_test TESTNAME SQL EXPECTED
54 # 63 #
55 # Commands providing a lower level interface to the global test counters: 64 # Commands providing a lower level interface to the global test counters:
56 # 65 #
57 # set_test_counter COUNTER ?VALUE? 66 # set_test_counter COUNTER ?VALUE?
58 # omit_test TESTNAME REASON 67 # omit_test TESTNAME REASON ?APPEND?
59 # fail_test TESTNAME 68 # fail_test TESTNAME
60 # incr_ntest 69 # incr_ntest
61 # 70 #
62 # Command run at the end of each test file: 71 # Command run at the end of each test file:
63 # 72 #
64 # finish_test 73 # finish_test
65 # 74 #
66 # Commands to help create test files that run with the "WAL" and other 75 # Commands to help create test files that run with the "WAL" and other
67 # permutations (see file permutations.test): 76 # permutations (see file permutations.test):
68 # 77 #
69 # wal_is_wal_mode 78 # wal_is_wal_mode
70 # wal_set_journal_mode ?DB? 79 # wal_set_journal_mode ?DB?
71 # wal_check_journal_mode TESTNAME?DB? 80 # wal_check_journal_mode TESTNAME?DB?
72 # permutation 81 # permutation
73 # presql 82 # presql
74 # 83 #
75 84
76 # Set the precision of FP arithmatic used by the interpreter. And 85 # Set the precision of FP arithmatic used by the interpreter. And
77 # configure SQLite to take database file locks on the page that begins 86 # 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 87 # 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 88 # the code that handles that special case can be tested without creating
80 # very large database files. 89 # very large database files.
81 # 90 #
82 set tcl_precision 15 91 set tcl_precision 15
83 sqlite3_test_control_pending_byte 0x0010000 92 sqlite3_test_control_pending_byte 0x0010000
84 93
85 94
86 # If the pager codec is available, create a wrapper for the [sqlite3] 95 # If the pager codec is available, create a wrapper for the [sqlite3]
87 # command that appends "-key {xyzzy}" to the command line. i.e. this: 96 # command that appends "-key {xyzzy}" to the command line. i.e. this:
88 # 97 #
89 # sqlite3 db test.db 98 # sqlite3 db test.db
90 # 99 #
91 # becomes 100 # becomes
92 # 101 #
93 # sqlite3 db test.db -key {xyzzy} 102 # sqlite3 db test.db -key {xyzzy}
94 # 103 #
95 if {[info command sqlite_orig]==""} { 104 if {[info command sqlite_orig]==""} {
96 rename sqlite3 sqlite_orig 105 rename sqlite3 sqlite_orig
(...skipping 11 matching lines...) Expand all
108 set res [uplevel 1 sqlite_orig $args] 117 set res [uplevel 1 sqlite_orig $args]
109 if {[info exists ::G(perm:presql)]} { 118 if {[info exists ::G(perm:presql)]} {
110 [lindex $args 0] eval $::G(perm:presql) 119 [lindex $args 0] eval $::G(perm:presql)
111 } 120 }
112 if {[info exists ::G(perm:dbconfig)]} { 121 if {[info exists ::G(perm:dbconfig)]} {
113 set ::dbhandle [lindex $args 0] 122 set ::dbhandle [lindex $args 0]
114 uplevel #0 $::G(perm:dbconfig) 123 uplevel #0 $::G(perm:dbconfig)
115 } 124 }
116 set res 125 set res
117 } else { 126 } else {
118 # This command is not opening a new database connection. Pass the 127 # This command is not opening a new database connection. Pass the
119 # arguments through to the C implemenation as the are. 128 # arguments through to the C implementation as the are.
120 # 129 #
121 uplevel 1 sqlite_orig $args 130 uplevel 1 sqlite_orig $args
122 } 131 }
123 } 132 }
124 } 133 }
125 134
135 proc getFileRetries {} {
136 if {![info exists ::G(file-retries)]} {
137 #
138 # NOTE: Return the default number of retries for [file] operations. A
139 # value of zero or less here means "disabled".
140 #
141 return [expr {$::tcl_platform(platform) eq "windows" ? 50 : 0}]
142 }
143 return $::G(file-retries)
144 }
145
146 proc getFileRetryDelay {} {
147 if {![info exists ::G(file-retry-delay)]} {
148 #
149 # NOTE: Return the default number of milliseconds to wait when retrying
150 # failed [file] operations. A value of zero or less means "do not
151 # wait".
152 #
153 return 100; # TODO: Good default?
154 }
155 return $::G(file-retry-delay)
156 }
157
158 # Return the string representing the name of the current directory. On
159 # Windows, the result is "normalized" to whatever our parent command shell
160 # is using to prevent case-mismatch issues.
161 #
162 proc get_pwd {} {
163 if {$::tcl_platform(platform) eq "windows"} {
164 #
165 # NOTE: Cannot use [file normalize] here because it would alter the
166 # case of the result to what Tcl considers canonical, which would
167 # defeat the purpose of this procedure.
168 #
169 return [string map [list \\ /] \
170 [string trim [exec -- $::env(ComSpec) /c echo %CD%]]]
171 } else {
172 return [pwd]
173 }
174 }
175
176 # Copy file $from into $to. This is used because some versions of
177 # TCL for windows (notably the 8.4.1 binary package shipped with the
178 # current mingw release) have a broken "file copy" command.
179 #
180 proc copy_file {from to} {
181 do_copy_file false $from $to
182 }
183
184 proc forcecopy {from to} {
185 do_copy_file true $from $to
186 }
187
188 proc do_copy_file {force from to} {
189 set nRetry [getFileRetries] ;# Maximum number of retries.
190 set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
191
192 # On windows, sometimes even a [file copy -force] can fail. The cause is
193 # usually "tag-alongs" - programs like anti-virus software, automatic backup
194 # tools and various explorer extensions that keep a file open a little longer
195 # than we expect, causing the delete to fail.
196 #
197 # The solution is to wait a short amount of time before retrying the copy.
198 #
199 if {$nRetry > 0} {
200 for {set i 0} {$i<$nRetry} {incr i} {
201 set rc [catch {
202 if {$force} {
203 file copy -force $from $to
204 } else {
205 file copy $from $to
206 }
207 } msg]
208 if {$rc==0} break
209 if {$nDelay > 0} { after $nDelay }
210 }
211 if {$rc} { error $msg }
212 } else {
213 if {$force} {
214 file copy -force $from $to
215 } else {
216 file copy $from $to
217 }
218 }
219 }
220
221 # Check if a file name is relative
222 #
223 proc is_relative_file { file } {
224 return [expr {[file pathtype $file] != "absolute"}]
225 }
226
227 # If the VFS supports using the current directory, returns [pwd];
228 # otherwise, it returns only the provided suffix string (which is
229 # empty by default).
230 #
231 proc test_pwd { args } {
232 if {[llength $args] > 0} {
233 set suffix1 [lindex $args 0]
234 if {[llength $args] > 1} {
235 set suffix2 [lindex $args 1]
236 } else {
237 set suffix2 $suffix1
238 }
239 } else {
240 set suffix1 ""; set suffix2 ""
241 }
242 ifcapable curdir {
243 return "[get_pwd]$suffix1"
244 } else {
245 return $suffix2
246 }
247 }
248
249 # Delete a file or directory
250 #
251 proc delete_file {args} {
252 do_delete_file false {*}$args
253 }
254
255 proc forcedelete {args} {
256 do_delete_file true {*}$args
257 }
258
259 proc do_delete_file {force args} {
260 set nRetry [getFileRetries] ;# Maximum number of retries.
261 set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
262
263 foreach filename $args {
264 # On windows, sometimes even a [file delete -force] can fail just after
265 # a file is closed. The cause is usually "tag-alongs" - programs like
266 # anti-virus software, automatic backup tools and various explorer
267 # extensions that keep a file open a little longer than we expect, causing
268 # the delete to fail.
269 #
270 # The solution is to wait a short amount of time before retrying the
271 # delete.
272 #
273 if {$nRetry > 0} {
274 for {set i 0} {$i<$nRetry} {incr i} {
275 set rc [catch {
276 if {$force} {
277 file delete -force $filename
278 } else {
279 file delete $filename
280 }
281 } msg]
282 if {$rc==0} break
283 if {$nDelay > 0} { after $nDelay }
284 }
285 if {$rc} { error $msg }
286 } else {
287 if {$force} {
288 file delete -force $filename
289 } else {
290 file delete $filename
291 }
292 }
293 }
294 }
295
296 if {$::tcl_platform(platform) eq "windows"} {
297 proc do_remove_win32_dir {args} {
298 set nRetry [getFileRetries] ;# Maximum number of retries.
299 set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
300
301 foreach dirName $args {
302 # On windows, sometimes even a [remove_win32_dir] can fail just after
303 # a directory is emptied. The cause is usually "tag-alongs" - programs
304 # like anti-virus software, automatic backup tools and various explorer
305 # extensions that keep a file open a little longer than we expect,
306 # causing the delete to fail.
307 #
308 # The solution is to wait a short amount of time before retrying the
309 # removal.
310 #
311 if {$nRetry > 0} {
312 for {set i 0} {$i < $nRetry} {incr i} {
313 set rc [catch {
314 remove_win32_dir $dirName
315 } msg]
316 if {$rc == 0} break
317 if {$nDelay > 0} { after $nDelay }
318 }
319 if {$rc} { error $msg }
320 } else {
321 remove_win32_dir $dirName
322 }
323 }
324 }
325
326 proc do_delete_win32_file {args} {
327 set nRetry [getFileRetries] ;# Maximum number of retries.
328 set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
329
330 foreach fileName $args {
331 # On windows, sometimes even a [delete_win32_file] can fail just after
332 # a file is closed. The cause is usually "tag-alongs" - programs like
333 # anti-virus software, automatic backup tools and various explorer
334 # extensions that keep a file open a little longer than we expect,
335 # causing the delete to fail.
336 #
337 # The solution is to wait a short amount of time before retrying the
338 # delete.
339 #
340 if {$nRetry > 0} {
341 for {set i 0} {$i < $nRetry} {incr i} {
342 set rc [catch {
343 delete_win32_file $fileName
344 } msg]
345 if {$rc == 0} break
346 if {$nDelay > 0} { after $nDelay }
347 }
348 if {$rc} { error $msg }
349 } else {
350 delete_win32_file $fileName
351 }
352 }
353 }
354 }
355
126 proc execpresql {handle args} { 356 proc execpresql {handle args} {
127 trace remove execution $handle enter [list execpresql $handle] 357 trace remove execution $handle enter [list execpresql $handle]
128 if {[info exists ::G(perm:presql)]} { 358 if {[info exists ::G(perm:presql)]} {
129 $handle eval $::G(perm:presql) 359 $handle eval $::G(perm:presql)
130 } 360 }
131 } 361 }
132 362
133 # This command should be called after loading tester.tcl from within 363 # This command should be called after loading tester.tcl from within
134 # all test scripts that are incompatible with encryption codecs. 364 # all test scripts that are incompatible with encryption codecs.
135 # 365 #
136 proc do_not_use_codec {} { 366 proc do_not_use_codec {} {
137 set ::do_not_use_codec 1 367 set ::do_not_use_codec 1
138 reset_db 368 reset_db
139 } 369 }
140 370
141 # The following block only runs the first time this file is sourced. It 371 # The following block only runs the first time this file is sourced. It
142 # does not run in slave interpreters (since the ::cmdlinearg array is 372 # does not run in slave interpreters (since the ::cmdlinearg array is
143 # populated before the test script is run in slave interpreters). 373 # populated before the test script is run in slave interpreters).
144 # 374 #
145 if {[info exists cmdlinearg]==0} { 375 if {[info exists cmdlinearg]==0} {
146 376
147 # Parse any options specified in the $argv array. This script accepts the 377 # Parse any options specified in the $argv array. This script accepts the
148 # following options: 378 # following options:
149 # 379 #
150 # --pause 380 # --pause
151 # --soft-heap-limit=NN 381 # --soft-heap-limit=NN
152 # --maxerror=NN 382 # --maxerror=NN
153 # --malloctrace=N 383 # --malloctrace=N
154 # --backtrace=N 384 # --backtrace=N
155 # --binarylog=N 385 # --binarylog=N
156 # --soak=N 386 # --soak=N
387 # --file-retries=N
388 # --file-retry-delay=N
157 # --start=[$permutation:]$testfile 389 # --start=[$permutation:]$testfile
390 # --match=$pattern
158 # 391 #
159 set cmdlinearg(soft-heap-limit) 0 392 set cmdlinearg(soft-heap-limit) 0
160 set cmdlinearg(maxerror) 1000 393 set cmdlinearg(maxerror) 1000
161 set cmdlinearg(malloctrace) 0 394 set cmdlinearg(malloctrace) 0
162 set cmdlinearg(backtrace) 10 395 set cmdlinearg(backtrace) 10
163 set cmdlinearg(binarylog) 0 396 set cmdlinearg(binarylog) 0
164 set cmdlinearg(soak) 0 397 set cmdlinearg(soak) 0
165 set cmdlinearg(start) "" 398 set cmdlinearg(file-retries) 0
399 set cmdlinearg(file-retry-delay) 0
400 set cmdlinearg(start) ""
401 set cmdlinearg(match) ""
166 402
167 set leftover [list] 403 set leftover [list]
168 foreach a $argv { 404 foreach a $argv {
169 switch -regexp -- $a { 405 switch -regexp -- $a {
170 {^-+pause$} { 406 {^-+pause$} {
171 # Wait for user input before continuing. This is to give the user an 407 # Wait for user input before continuing. This is to give the user an
172 # opportunity to connect profiling tools to the process. 408 # opportunity to connect profiling tools to the process.
173 puts -nonewline "Press RETURN to begin..." 409 puts -nonewline "Press RETURN to begin..."
174 flush stdout 410 flush stdout
175 gets stdin 411 gets stdin
176 } 412 }
177 {^-+soft-heap-limit=.+$} { 413 {^-+soft-heap-limit=.+$} {
178 foreach {dummy cmdlinearg(soft-heap-limit)} [split $a =] break 414 foreach {dummy cmdlinearg(soft-heap-limit)} [split $a =] break
179 } 415 }
180 {^-+maxerror=.+$} { 416 {^-+maxerror=.+$} {
181 foreach {dummy cmdlinearg(maxerror)} [split $a =] break 417 foreach {dummy cmdlinearg(maxerror)} [split $a =] break
182 } 418 }
183 {^-+malloctrace=.+$} { 419 {^-+malloctrace=.+$} {
184 foreach {dummy cmdlinearg(malloctrace)} [split $a =] break 420 foreach {dummy cmdlinearg(malloctrace)} [split $a =] break
185 if {$cmdlinearg(malloctrace)} { 421 if {$cmdlinearg(malloctrace)} {
186 sqlite3_memdebug_log start 422 sqlite3_memdebug_log start
187 } 423 }
188 } 424 }
189 {^-+backtrace=.+$} { 425 {^-+backtrace=.+$} {
190 foreach {dummy cmdlinearg(backtrace)} [split $a =] break 426 foreach {dummy cmdlinearg(backtrace)} [split $a =] break
191 sqlite3_memdebug_backtrace $value 427 sqlite3_memdebug_backtrace $value
192 } 428 }
193 {^-+binarylog=.+$} { 429 {^-+binarylog=.+$} {
194 foreach {dummy cmdlinearg(binarylog)} [split $a =] break 430 foreach {dummy cmdlinearg(binarylog)} [split $a =] break
195 } 431 }
196 {^-+soak=.+$} { 432 {^-+soak=.+$} {
197 foreach {dummy cmdlinearg(soak)} [split $a =] break 433 foreach {dummy cmdlinearg(soak)} [split $a =] break
198 set ::G(issoak) $cmdlinearg(soak) 434 set ::G(issoak) $cmdlinearg(soak)
199 } 435 }
436 {^-+file-retries=.+$} {
437 foreach {dummy cmdlinearg(file-retries)} [split $a =] break
438 set ::G(file-retries) $cmdlinearg(file-retries)
439 }
440 {^-+file-retry-delay=.+$} {
441 foreach {dummy cmdlinearg(file-retry-delay)} [split $a =] break
442 set ::G(file-retry-delay) $cmdlinearg(file-retry-delay)
443 }
200 {^-+start=.+$} { 444 {^-+start=.+$} {
201 foreach {dummy cmdlinearg(start)} [split $a =] break 445 foreach {dummy cmdlinearg(start)} [split $a =] break
202 446
203 set ::G(start:file) $cmdlinearg(start) 447 set ::G(start:file) $cmdlinearg(start)
204 if {[regexp {(.*):(.*)} $cmdlinearg(start) -> s.perm s.file]} { 448 if {[regexp {(.*):(.*)} $cmdlinearg(start) -> s.perm s.file]} {
205 set ::G(start:permutation) ${s.perm} 449 set ::G(start:permutation) ${s.perm}
206 set ::G(start:file) ${s.file} 450 set ::G(start:file) ${s.file}
207 } 451 }
208 if {$::G(start:file) == ""} {unset ::G(start:file)} 452 if {$::G(start:file) == ""} {unset ::G(start:file)}
209 } 453 }
454 {^-+match=.+$} {
455 foreach {dummy cmdlinearg(match)} [split $a =] break
456
457 set ::G(match) $cmdlinearg(match)
458 if {$::G(match) == ""} {unset ::G(match)}
459 }
210 default { 460 default {
211 lappend leftover $a 461 lappend leftover $a
212 } 462 }
213 } 463 }
214 } 464 }
215 set argv $leftover 465 set argv $leftover
216 466
217 # Install the malloc layer used to inject OOM errors. And the 'automatic' 467 # Install the malloc layer used to inject OOM errors. And the 'automatic'
218 # extensions. This only needs to be done once for the process. 468 # extensions. This only needs to be done once for the process.
219 # 469 #
220 sqlite3_shutdown 470 sqlite3_shutdown
221 install_malloc_faultsim 1 471 install_malloc_faultsim 1
222 sqlite3_initialize 472 sqlite3_initialize
223 autoinstall_test_functions 473 autoinstall_test_functions
224 474
225 # If the --binarylog option was specified, create the logging VFS. This 475 # If the --binarylog option was specified, create the logging VFS. This
226 # call installs the new VFS as the default for all SQLite connections. 476 # call installs the new VFS as the default for all SQLite connections.
227 # 477 #
228 if {$cmdlinearg(binarylog)} { 478 if {$cmdlinearg(binarylog)} {
229 vfslog new binarylog {} vfslog.bin 479 vfslog new binarylog {} vfslog.bin
230 } 480 }
231 481
232 # Set the backtrace depth, if malloc tracing is enabled. 482 # Set the backtrace depth, if malloc tracing is enabled.
233 # 483 #
234 if {$cmdlinearg(malloctrace)} { 484 if {$cmdlinearg(malloctrace)} {
235 sqlite3_memdebug_backtrace $cmdlinearg(backtrace) 485 sqlite3_memdebug_backtrace $cmdlinearg(backtrace)
236 } 486 }
237 } 487 }
238 488
239 # Update the soft-heap-limit each time this script is run. In that 489 # Update the soft-heap-limit each time this script is run. In that
240 # way if an individual test file changes the soft-heap-limit, it 490 # way if an individual test file changes the soft-heap-limit, it
241 # will be reset at the start of the next test file. 491 # will be reset at the start of the next test file.
242 # 492 #
243 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) 493 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
244 494
245 # Create a test database 495 # Create a test database
246 # 496 #
247 proc reset_db {} { 497 proc reset_db {} {
248 catch {db close} 498 catch {db close}
249 file delete -force test.db 499 forcedelete test.db
250 file delete -force test.db-journal 500 forcedelete test.db-journal
251 file delete -force test.db-wal 501 forcedelete test.db-wal
252 sqlite3 db ./test.db 502 sqlite3 db ./test.db
253 set ::DB [sqlite3_connection_pointer db] 503 set ::DB [sqlite3_connection_pointer db]
254 if {[info exists ::SETUP_SQL]} { 504 if {[info exists ::SETUP_SQL]} {
255 db eval $::SETUP_SQL 505 db eval $::SETUP_SQL
256 } 506 }
257 } 507 }
258 reset_db 508 reset_db
259 509
260 # Abort early if this script has been run before. 510 # Abort early if this script has been run before.
261 # 511 #
262 if {[info exists TC(count)]} return 512 if {[info exists TC(count)]} return
263 513
264 # Make sure memory statistics are enabled. 514 # Make sure memory statistics are enabled.
265 # 515 #
266 sqlite3_config_memstatus 1 516 sqlite3_config_memstatus 1
267 517
268 # Initialize the test counters and set up commands to access them. 518 # Initialize the test counters and set up commands to access them.
269 # Or, if this is a slave interpreter, set up aliases to write the 519 # Or, if this is a slave interpreter, set up aliases to write the
270 # counters in the parent interpreter. 520 # counters in the parent interpreter.
271 # 521 #
272 if {0==[info exists ::SLAVE]} { 522 if {0==[info exists ::SLAVE]} {
273 set TC(errors) 0 523 set TC(errors) 0
274 set TC(count) 0 524 set TC(count) 0
275 set TC(fail_list) [list] 525 set TC(fail_list) [list]
276 set TC(omit_list) [list] 526 set TC(omit_list) [list]
527 set TC(warn_list) [list]
277 528
278 proc set_test_counter {counter args} { 529 proc set_test_counter {counter args} {
279 if {[llength $args]} { 530 if {[llength $args]} {
280 set ::TC($counter) [lindex $args 0] 531 set ::TC($counter) [lindex $args 0]
281 } 532 }
282 set ::TC($counter) 533 set ::TC($counter)
283 } 534 }
284 } 535 }
285 536
286 # Record the fact that a sequence of tests were omitted. 537 # Record the fact that a sequence of tests were omitted.
287 # 538 #
288 proc omit_test {name reason} { 539 proc omit_test {name reason {append 1}} {
289 set omitList [set_test_counter omit_list] 540 set omitList [set_test_counter omit_list]
290 lappend omitList [list $name $reason] 541 if {$append} {
542 lappend omitList [list $name $reason]
543 }
291 set_test_counter omit_list $omitList 544 set_test_counter omit_list $omitList
292 } 545 }
293 546
294 # Record the fact that a test failed. 547 # Record the fact that a test failed.
295 # 548 #
296 proc fail_test {name} { 549 proc fail_test {name} {
297 set f [set_test_counter fail_list] 550 set f [set_test_counter fail_list]
298 lappend f $name 551 lappend f $name
299 set_test_counter fail_list $f 552 set_test_counter fail_list $f
300 set_test_counter errors [expr [set_test_counter errors] + 1] 553 set_test_counter errors [expr [set_test_counter errors] + 1]
301 554
302 set nFail [set_test_counter errors] 555 set nFail [set_test_counter errors]
303 if {$nFail>=$::cmdlinearg(maxerror)} { 556 if {$nFail>=$::cmdlinearg(maxerror)} {
304 puts "*** Giving up..." 557 puts "*** Giving up..."
305 finalize_testing 558 finalize_testing
306 } 559 }
307 } 560 }
308 561
562 # Remember a warning message to be displayed at the conclusion of all testing
563 #
564 proc warning {msg {append 1}} {
565 puts "Warning: $msg"
566 set warnList [set_test_counter warn_list]
567 if {$append} {
568 lappend warnList $msg
569 }
570 set_test_counter warn_list $warnList
571 }
572
573
309 # Increment the number of tests run 574 # Increment the number of tests run
310 # 575 #
311 proc incr_ntest {} { 576 proc incr_ntest {} {
312 set_test_counter count [expr [set_test_counter count] + 1] 577 set_test_counter count [expr [set_test_counter count] + 1]
313 } 578 }
314 579
315 580
316 # Invoke the do_test procedure to run a single test 581 # Invoke the do_test procedure to run a single test
317 # 582 #
318 proc do_test {name cmd expected} { 583 proc do_test {name cmd expected} {
319
320 global argv cmdlinearg 584 global argv cmdlinearg
321 585
322 fix_testname name 586 fix_testname name
323 587
324 sqlite3_memdebug_settitle $name 588 sqlite3_memdebug_settitle $name
325 589
326 # if {[llength $argv]==0} { 590 # if {[llength $argv]==0} {
327 # set go 1 591 # set go 1
328 # } else { 592 # } else {
329 # set go 0 593 # set go 0
330 # foreach pattern $argv { 594 # foreach pattern $argv {
331 # if {[string match $pattern $name]} { 595 # if {[string match $pattern $name]} {
332 # set go 1 596 # set go 1
333 # break 597 # break
334 # } 598 # }
335 # } 599 # }
336 # } 600 # }
337 601
338 if {[info exists ::G(perm:prefix)]} { 602 if {[info exists ::G(perm:prefix)]} {
339 set name "$::G(perm:prefix)$name" 603 set name "$::G(perm:prefix)$name"
340 } 604 }
341 605
342 incr_ntest 606 incr_ntest
343 puts -nonewline $name... 607 puts -nonewline $name...
344 flush stdout 608 flush stdout
345 if {[catch {uplevel #0 "$cmd;\n"} result]} { 609
346 puts "\nError: $result" 610 if {![info exists ::G(match)] || [string match $::G(match) $name]} {
347 fail_test $name 611 if {[catch {uplevel #0 "$cmd;\n"} result]} {
348 } elseif {[string compare $result $expected]} { 612 puts "\nError: $result"
349 puts "\nExpected: \[$expected\]\n Got: \[$result\]" 613 fail_test $name
350 fail_test $name 614 } else {
615 if {[regexp {^~?/.*/$} $expected]} {
616 # "expected" is of the form "/PATTERN/" then the result if correct if
617 # regular expression PATTERN matches the result. "~/PATTERN/" means
618 # the regular expression must not match.
619 if {[string index $expected 0]=="~"} {
620 set re [string range $expected 2 end-1]
621 if {[string index $re 0]=="*"} {
622 # If the regular expression begins with * then treat it as a glob in stead
623 set ok [string match $re $result]
624 } else {
625 set re [string map {# {[-0-9.]+}} $re]
626 set ok [regexp $re $result]
627 }
628 set ok [expr {!$ok}]
629 } else {
630 set re [string range $expected 1 end-1]
631 if {[string index $re 0]=="*"} {
632 # If the regular expression begins with * then treat it as a glob in stead
633 set ok [string match $re $result]
634 } else {
635 set re [string map {# {[-0-9.]+}} $re]
636 set ok [regexp $re $result]
637 }
638 }
639 } elseif {[regexp {^~?\*.*\*$} $expected]} {
640 # "expected" is of the form "*GLOB*" then the result if correct if
641 # glob pattern GLOB matches the result. "~/GLOB/" means
642 # the glob must not match.
643 if {[string index $expected 0]=="~"} {
644 set e [string range $expected 1 end]
645 set ok [expr {![string match $e $result]}]
646 } else {
647 set ok [string match $expected $result]
648 }
649 } else {
650 set ok [expr {[string compare $result $expected]==0}]
651 }
652 if {!$ok} {
653 # if {![info exists ::testprefix] || $::testprefix eq ""} {
654 # error "no test prefix"
655 # }
656 puts "\nExpected: \[$expected\]\n Got: \[$result\]"
657 fail_test $name
658 } else {
659 puts " Ok"
660 }
661 }
351 } else { 662 } else {
352 puts " Ok" 663 puts " Omitted"
664 omit_test $name "pattern mismatch" 0
353 } 665 }
354 flush stdout 666 flush stdout
355 } 667 }
356 668
669 proc catchcmd {db {cmd ""}} {
670 global CLI
671 set out [open cmds.txt w]
672 puts $out $cmd
673 close $out
674 set line "exec $CLI $db < cmds.txt"
675 set rc [catch { eval $line } msg]
676 list $rc $msg
677 }
678
679 proc filepath_normalize {p} {
680 # test cases should be written to assume "unix"-like file paths
681 if {$::tcl_platform(platform)!="unix"} {
682 # lreverse*2 as a hack to remove any unneeded {} after the string map
683 lreverse [lreverse [string map {\\ /} [regsub -nocase -all {[a-z]:[/\\]+} $p {/}]]]
684 } {
685 set p
686 }
687 }
688 proc do_filepath_test {name cmd expected} {
689 uplevel [list do_test $name [
690 subst -nocommands { filepath_normalize [ $cmd ] }
691 ] [filepath_normalize $expected]]
692 }
693
694 proc realnum_normalize {r} {
695 # different TCL versions display floating point values differently.
696 string map {1.#INF inf Inf inf .0e e} [regsub -all {(e[+-])0+} $r {\1}]
697 }
698 proc do_realnum_test {name cmd expected} {
699 uplevel [list do_test $name [
700 subst -nocommands { realnum_normalize [ $cmd ] }
701 ] [realnum_normalize $expected]]
702 }
703
357 proc fix_testname {varname} { 704 proc fix_testname {varname} {
358 upvar $varname testname 705 upvar $varname testname
359 if {[info exists ::testprefix] 706 if {[info exists ::testprefix]
360 && [string is digit [string range $testname 0 0]] 707 && [string is digit [string range $testname 0 0]]
361 } { 708 } {
362 set testname "${::testprefix}-$testname" 709 set testname "${::testprefix}-$testname"
363 } 710 }
364 } 711 }
365 712
366 proc do_execsql_test {testname sql {result {}}} { 713 proc do_execsql_test {testname sql {result {}}} {
367 fix_testname testname 714 fix_testname testname
368 uplevel do_test $testname [list "execsql {$sql}"] [list [list {*}$result]] 715 uplevel do_test [list $testname] [list "execsql {$sql}"] [list [list {*}$resul t]]
369 } 716 }
370 proc do_catchsql_test {testname sql result} { 717 proc do_catchsql_test {testname sql result} {
371 fix_testname testname 718 fix_testname testname
372 uplevel do_test $testname [list "catchsql {$sql}"] [list $result] 719 uplevel do_test [list $testname] [list "catchsql {$sql}"] [list $result]
720 }
721 proc do_timed_execsql_test {testname sql {result {}}} {
722 fix_testname testname
723 uplevel do_test [list $testname] [list "execsql_timed {$sql}"]\
724 [list [list {*}$result]]
373 } 725 }
374 proc do_eqp_test {name sql res} { 726 proc do_eqp_test {name sql res} {
375 uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res] 727 uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
376 } 728 }
377 729
378 #------------------------------------------------------------------------- 730 #-------------------------------------------------------------------------
379 # Usage: do_select_tests PREFIX ?SWITCHES? TESTLIST 731 # Usage: do_select_tests PREFIX ?SWITCHES? TESTLIST
380 # 732 #
381 # Where switches are: 733 # Where switches are:
382 # 734 #
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 } 793 }
442 794
443 } 795 }
444 796
445 proc delete_all_data {} { 797 proc delete_all_data {} {
446 db eval {SELECT tbl_name AS t FROM sqlite_master WHERE type = 'table'} { 798 db eval {SELECT tbl_name AS t FROM sqlite_master WHERE type = 'table'} {
447 db eval "DELETE FROM '[string map {' ''} $t]'" 799 db eval "DELETE FROM '[string map {' ''} $t]'"
448 } 800 }
449 } 801 }
450 802
451 # Run an SQL script. 803 # Run an SQL script.
452 # Return the number of microseconds per statement. 804 # Return the number of microseconds per statement.
453 # 805 #
454 proc speed_trial {name numstmt units sql} { 806 proc speed_trial {name numstmt units sql} {
455 puts -nonewline [format {%-21.21s } $name...] 807 puts -nonewline [format {%-21.21s } $name...]
456 flush stdout 808 flush stdout
457 set speed [time {sqlite3_exec_nr db $sql}] 809 set speed [time {sqlite3_exec_nr db $sql}]
458 set tm [lindex $speed 0] 810 set tm [lindex $speed 0]
459 if {$tm == 0} { 811 if {$tm == 0} {
460 set rate [format %20s "many"] 812 set rate [format %20s "many"]
461 } else { 813 } else {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 foreach {test us} $::speed_trial_times { 856 foreach {test us} $::speed_trial_times {
505 puts "INSERT INTO time VALUES('$vers', '$name', '$test', $us);" 857 puts "INSERT INTO time VALUES('$vers', '$name', '$test', $us);"
506 } 858 }
507 } 859 }
508 } 860 }
509 861
510 # Run this routine last 862 # Run this routine last
511 # 863 #
512 proc finish_test {} { 864 proc finish_test {} {
513 catch {db close} 865 catch {db close}
866 catch {db1 close}
514 catch {db2 close} 867 catch {db2 close}
515 catch {db3 close} 868 catch {db3 close}
516 if {0==[info exists ::SLAVE]} { finalize_testing } 869 if {0==[info exists ::SLAVE]} { finalize_testing }
517 } 870 }
518 proc finalize_testing {} { 871 proc finalize_testing {} {
519 global sqlite_open_file_count 872 global sqlite_open_file_count
520 873
521 set omitList [set_test_counter omit_list] 874 set omitList [set_test_counter omit_list]
522 875
523 catch {db close} 876 catch {db close}
524 catch {db2 close} 877 catch {db2 close}
525 catch {db3 close} 878 catch {db3 close}
526 879
527 vfs_unlink_test 880 vfs_unlink_test
528 sqlite3 db {} 881 sqlite3 db {}
529 # sqlite3_clear_tsd_memdebug 882 # sqlite3_clear_tsd_memdebug
530 db close 883 db close
531 sqlite3_reset_auto_extension 884 sqlite3_reset_auto_extension
532 885
533 sqlite3_soft_heap_limit 0 886 sqlite3_soft_heap_limit 0
534 set nTest [incr_ntest] 887 set nTest [incr_ntest]
535 set nErr [set_test_counter errors] 888 set nErr [set_test_counter errors]
536 889
537 puts "$nErr errors out of $nTest tests" 890 set nKnown 0
538 if {$nErr>0} { 891 if {[file readable known-problems.txt]} {
539 puts "Failures on these tests: [set_test_counter fail_list]" 892 set fd [open known-problems.txt]
893 set content [read $fd]
894 close $fd
895 foreach x $content {set known_error($x) 1}
896 foreach x [set_test_counter fail_list] {
897 if {[info exists known_error($x)]} {incr nKnown}
898 }
899 }
900 if {$nKnown>0} {
901 puts "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\
902 out of $nTest tests"
903 } else {
904 puts "$nErr errors out of $nTest tests"
905 }
906 if {$nErr>$nKnown} {
907 puts -nonewline "Failures on these tests:"
908 foreach x [set_test_counter fail_list] {
909 if {![info exists known_error($x)]} {puts -nonewline " $x"}
910 }
911 puts ""
912 }
913 foreach warning [set_test_counter warn_list] {
914 puts "Warning: $warning"
540 } 915 }
541 run_thread_tests 1 916 run_thread_tests 1
542 if {[llength $omitList]>0} { 917 if {[llength $omitList]>0} {
543 puts "Omitted test cases:" 918 puts "Omitted test cases:"
544 set prec {} 919 set prec {}
545 foreach {rec} [lsort $omitList] { 920 foreach {rec} [lsort $omitList] {
546 if {$rec==$prec} continue 921 if {$rec==$prec} continue
547 set prec $rec 922 set prec $rec
548 puts [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]] 923 puts [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]]
549 } 924 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 sqlite3_memdebug_log stop 965 sqlite3_memdebug_log stop
591 sqlite3_memdebug_log clear 966 sqlite3_memdebug_log clear
592 967
593 if {[sqlite3_memory_used]>0} { 968 if {[sqlite3_memory_used]>0} {
594 puts "Writing leaks.sql..." 969 puts "Writing leaks.sql..."
595 sqlite3_memdebug_log sync 970 sqlite3_memdebug_log sync
596 memdebug_log_sql leaks.sql 971 memdebug_log_sql leaks.sql
597 } 972 }
598 } 973 }
599 foreach f [glob -nocomplain test.db-*-journal] { 974 foreach f [glob -nocomplain test.db-*-journal] {
600 file delete -force $f 975 forcedelete $f
601 } 976 }
602 foreach f [glob -nocomplain test.db-mj*] { 977 foreach f [glob -nocomplain test.db-mj*] {
603 file delete -force $f 978 forcedelete $f
604 } 979 }
605 exit [expr {$nErr>0}] 980 exit [expr {$nErr>0}]
606 } 981 }
607 982
608 # Display memory statistics for analysis and debugging purposes. 983 # Display memory statistics for analysis and debugging purposes.
609 # 984 #
610 proc show_memstats {} { 985 proc show_memstats {} {
611 set x [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 986 set x [sqlite3_status SQLITE_STATUS_MEMORY_USED 0]
612 set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 987 set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
613 set val [format {now %10d max %10d max-size %10d} \ 988 set val [format {now %10d max %10d max-size %10d} \
(...skipping 24 matching lines...) Expand all
638 puts "Parser stack depth: $val" 1013 puts "Parser stack depth: $val"
639 } 1014 }
640 } 1015 }
641 1016
642 # A procedure to execute SQL 1017 # A procedure to execute SQL
643 # 1018 #
644 proc execsql {sql {db db}} { 1019 proc execsql {sql {db db}} {
645 # puts "SQL = $sql" 1020 # puts "SQL = $sql"
646 uplevel [list $db eval $sql] 1021 uplevel [list $db eval $sql]
647 } 1022 }
1023 proc execsql_timed {sql {db db}} {
1024 set tm [time {
1025 set x [uplevel [list $db eval $sql]]
1026 } 1]
1027 set tm [lindex $tm 0]
1028 puts -nonewline " ([expr {$tm*0.001}]ms) "
1029 set x
1030 }
648 1031
649 # Execute SQL and catch exceptions. 1032 # Execute SQL and catch exceptions.
650 # 1033 #
651 proc catchsql {sql {db db}} { 1034 proc catchsql {sql {db db}} {
652 # puts "SQL = $sql" 1035 # puts "SQL = $sql"
653 set r [catch [list uplevel [list $db eval $sql]] msg] 1036 set r [catch [list uplevel [list $db eval $sql]] msg]
654 lappend r $msg 1037 lappend r $msg
655 return $r 1038 return $r
656 } 1039 }
657 1040
658 # Do an VDBE code dump on the SQL given 1041 # Do an VDBE code dump on the SQL given
659 # 1042 #
660 proc explain {sql {db db}} { 1043 proc explain {sql {db db}} {
661 puts "" 1044 puts ""
662 puts "addr opcode p1 p2 p3 p4 p5 #" 1045 puts "addr opcode p1 p2 p3 p4 p5 #"
663 puts "---- ------------ ------ ------ ------ --------------- -- -" 1046 puts "---- ------------ ------ ------ ------ --------------- -- -"
664 $db eval "explain $sql" {} { 1047 $db eval "explain $sql" {} {
665 puts [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \ 1048 puts [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \
666 $addr $opcode $p1 $p2 $p3 $p4 $p5 $comment 1049 $addr $opcode $p1 $p2 $p3 $p4 $p5 $comment
667 ] 1050 ]
668 } 1051 }
669 } 1052 }
670 1053
1054 proc explain_i {sql {db db}} {
1055 puts ""
1056 puts "addr opcode p1 p2 p3 p4 p5 #"
1057 puts "---- ------------ ------ ------ ------ ---------------- -- -"
1058
1059
1060 # Set up colors for the different opcodes. Scheme is as follows:
1061 #
1062 # Red: Opcodes that write to a b-tree.
1063 # Blue: Opcodes that reposition or seek a cursor.
1064 # Green: The ResultRow opcode.
1065 #
1066 if { [catch {fconfigure stdout -mode}]==0 } {
1067 set R "\033\[31;1m" ;# Red fg
1068 set G "\033\[32;1m" ;# Green fg
1069 set B "\033\[34;1m" ;# Red fg
1070 set D "\033\[39;0m" ;# Default fg
1071 } else {
1072 set R ""
1073 set G ""
1074 set B ""
1075 set D ""
1076 }
1077 foreach opcode {
1078 Seek SeekGe SeekGt SeekLe SeekLt NotFound Last Rewind
1079 NoConflict Next Prev VNext VPrev VFilter
1080 SorterSort SorterNext
1081 } {
1082 set color($opcode) $B
1083 }
1084 foreach opcode {ResultRow} {
1085 set color($opcode) $G
1086 }
1087 foreach opcode {IdxInsert Insert Delete IdxDelete} {
1088 set color($opcode) $R
1089 }
1090
1091 set bSeenGoto 0
1092 $db eval "explain $sql" {} {
1093 set x($addr) 0
1094 set op($addr) $opcode
1095
1096 if {$opcode == "Goto" && ($bSeenGoto==0 || ($p2 > $addr+10))} {
1097 set linebreak($p2) 1
1098 set bSeenGoto 1
1099 }
1100
1101 if {$opcode=="Next" || $opcode=="Prev"
1102 || $opcode=="VNext" || $opcode=="VPrev"
1103 || $opcode=="SorterNext"
1104 } {
1105 for {set i $p2} {$i<$addr} {incr i} {
1106 incr x($i) 2
1107 }
1108 }
1109
1110 if {$opcode == "Goto" && $p2<$addr && $op($p2)=="Yield"} {
1111 for {set i [expr $p2+1]} {$i<$addr} {incr i} {
1112 incr x($i) 2
1113 }
1114 }
1115
1116 if {$opcode == "Halt" && $comment == "End of coroutine"} {
1117 set linebreak([expr $addr+1]) 1
1118 }
1119 }
1120
1121 $db eval "explain $sql" {} {
1122 if {[info exists linebreak($addr)]} {
1123 puts ""
1124 }
1125 set I [string repeat " " $x($addr)]
1126
1127 set col ""
1128 catch { set col $color($opcode) }
1129
1130 puts [format {%-4d %s%s%-12.12s%s %-6d %-6d %-6d % -17s %s %s} \
1131 $addr $I $col $opcode $D $p1 $p2 $p3 $p4 $p5 $comment
1132 ]
1133 }
1134 puts "---- ------------ ------ ------ ------ ---------------- -- -"
1135 }
1136
671 # Show the VDBE program for an SQL statement but omit the Trace 1137 # Show the VDBE program for an SQL statement but omit the Trace
672 # opcode at the beginning. This procedure can be used to prove 1138 # opcode at the beginning. This procedure can be used to prove
673 # that different SQL statements generate exactly the same VDBE code. 1139 # that different SQL statements generate exactly the same VDBE code.
674 # 1140 #
675 proc explain_no_trace {sql} { 1141 proc explain_no_trace {sql} {
676 set tr [db eval "EXPLAIN $sql"] 1142 set tr [db eval "EXPLAIN $sql"]
677 return [lrange $tr 7 end] 1143 return [lrange $tr 7 end]
678 } 1144 }
679 1145
680 # Another procedure to execute SQL. This one includes the field 1146 # Another procedure to execute SQL. This one includes the field
681 # names in the returned list. 1147 # names in the returned list.
682 # 1148 #
683 proc execsql2 {sql} { 1149 proc execsql2 {sql} {
684 set result {} 1150 set result {}
685 db eval $sql data { 1151 db eval $sql data {
686 foreach f $data(*) { 1152 foreach f $data(*) {
687 lappend result $f $data($f) 1153 lappend result $f $data($f)
688 } 1154 }
689 } 1155 }
690 return $result 1156 return $result
691 } 1157 }
692 1158
1159 # Use a temporary in-memory database to execute SQL statements
1160 #
1161 proc memdbsql {sql} {
1162 sqlite3 memdb :memory:
1163 set result [memdb eval $sql]
1164 memdb close
1165 return $result
1166 }
1167
693 # Use the non-callback API to execute multiple SQL statements 1168 # Use the non-callback API to execute multiple SQL statements
694 # 1169 #
695 proc stepsql {dbptr sql} { 1170 proc stepsql {dbptr sql} {
696 set sql [string trim $sql] 1171 set sql [string trim $sql]
697 set r 0 1172 set r 0
698 while {[string length $sql]>0} { 1173 while {[string length $sql]>0} {
699 if {[catch {sqlite3_prepare $dbptr $sql -1 sqltail} vm]} { 1174 if {[catch {sqlite3_prepare $dbptr $sql -1 sqltail} vm]} {
700 return [list 1 $vm] 1175 return [list 1 $vm]
701 } 1176 }
702 set sql [string trim $sqltail] 1177 set sql [string trim $sqltail]
703 # while {[sqlite_step $vm N VAL COL]=="SQLITE_ROW"} { 1178 # while {[sqlite_step $vm N VAL COL]=="SQLITE_ROW"} {
704 # foreach v $VAL {lappend r $v} 1179 # foreach v $VAL {lappend r $v}
705 # } 1180 # }
706 while {[sqlite3_step $vm]=="SQLITE_ROW"} { 1181 while {[sqlite3_step $vm]=="SQLITE_ROW"} {
707 for {set i 0} {$i<[sqlite3_data_count $vm]} {incr i} { 1182 for {set i 0} {$i<[sqlite3_data_count $vm]} {incr i} {
708 lappend r [sqlite3_column_text $vm $i] 1183 lappend r [sqlite3_column_text $vm $i]
709 } 1184 }
710 } 1185 }
711 if {[catch {sqlite3_finalize $vm} errmsg]} { 1186 if {[catch {sqlite3_finalize $vm} errmsg]} {
712 return [list 1 $errmsg] 1187 return [list 1 $errmsg]
713 } 1188 }
714 } 1189 }
715 return $r 1190 return $r
716 } 1191 }
717 1192
718 # Delete a file or directory
719 #
720 proc forcedelete {args} {
721 foreach filename $args {
722 # On windows, sometimes even a [file delete -force] can fail just after
723 # a file is closed. The cause is usually "tag-alongs" - programs like
724 # anti-virus software, automatic backup tools and various explorer
725 # extensions that keep a file open a little longer than we expect, causing
726 # the delete to fail.
727 #
728 # The solution is to wait a short amount of time before retrying the
729 # delete.
730 #
731 set nRetry 50 ;# Maximum number of retries.
732 set nDelay 100 ;# Delay in ms before retrying.
733 for {set i 0} {$i<$nRetry} {incr i} {
734 set rc [catch {file delete -force $filename} msg]
735 if {$rc==0} break
736 after $nDelay
737 }
738 if {$rc} { error $msg }
739 }
740 }
741
742 # Do an integrity check of the entire database 1193 # Do an integrity check of the entire database
743 # 1194 #
744 proc integrity_check {name {db db}} { 1195 proc integrity_check {name {db db}} {
745 ifcapable integrityck { 1196 ifcapable integrityck {
746 do_test $name [list execsql {PRAGMA integrity_check} $db] {ok} 1197 do_test $name [list execsql {PRAGMA integrity_check} $db] {ok}
747 } 1198 }
748 } 1199 }
749 1200
1201 # Check the extended error code
1202 #
1203 proc verify_ex_errcode {name expected {db db}} {
1204 do_test $name [list sqlite3_extended_errcode $db] $expected
1205 }
1206
1207
1208 # Return true if the SQL statement passed as the second argument uses a
1209 # statement transaction.
1210 #
1211 proc sql_uses_stmt {db sql} {
1212 set stmt [sqlite3_prepare $db $sql -1 dummy]
1213 set uses [uses_stmt_journal $stmt]
1214 sqlite3_finalize $stmt
1215 return $uses
1216 }
1217
750 proc fix_ifcapable_expr {expr} { 1218 proc fix_ifcapable_expr {expr} {
751 set ret "" 1219 set ret ""
752 set state 0 1220 set state 0
753 for {set i 0} {$i < [string length $expr]} {incr i} { 1221 for {set i 0} {$i < [string length $expr]} {incr i} {
754 set char [string range $expr $i $i] 1222 set char [string range $expr $i $i]
755 set newstate [expr {[string is alnum $char] || $char eq "_"}] 1223 set newstate [expr {[string is alnum $char] || $char eq "_"}]
756 if {$newstate && !$state} { 1224 if {$newstate && !$state} {
757 append ret {$::sqlite_options(} 1225 append ret {$::sqlite_options(}
758 } 1226 }
759 if {!$newstate && $state} { 1227 if {!$newstate && $state} {
760 append ret ) 1228 append ret )
761 } 1229 }
762 append ret $char 1230 append ret $char
763 set state $newstate 1231 set state $newstate
764 } 1232 }
765 if {$state} {append ret )} 1233 if {$state} {append ret )}
766 return $ret 1234 return $ret
767 } 1235 }
768 1236
1237 # Returns non-zero if the capabilities are present; zero otherwise.
1238 #
1239 proc capable {expr} {
1240 set e [fix_ifcapable_expr $expr]; return [expr ($e)]
1241 }
1242
769 # Evaluate a boolean expression of capabilities. If true, execute the 1243 # Evaluate a boolean expression of capabilities. If true, execute the
770 # code. Omit the code if false. 1244 # code. Omit the code if false.
771 # 1245 #
772 proc ifcapable {expr code {else ""} {elsecode ""}} { 1246 proc ifcapable {expr code {else ""} {elsecode ""}} {
773 #regsub -all {[a-z_0-9]+} $expr {$::sqlite_options(&)} e2 1247 #regsub -all {[a-z_0-9]+} $expr {$::sqlite_options(&)} e2
774 set e2 [fix_ifcapable_expr $expr] 1248 set e2 [fix_ifcapable_expr $expr]
775 if ($e2) { 1249 if ($e2) {
776 set c [catch {uplevel 1 $code} r] 1250 set c [catch {uplevel 1 $code} r]
777 } else { 1251 } else {
778 set c [catch {uplevel 1 $elsecode} r] 1252 set c [catch {uplevel 1 $elsecode} r]
779 } 1253 }
780 return -code $c $r 1254 return -code $c $r
781 } 1255 }
782 1256
783 # This proc execs a seperate process that crashes midway through executing 1257 # This proc execs a seperate process that crashes midway through executing
784 # the SQL script $sql on database test.db. 1258 # the SQL script $sql on database test.db.
785 # 1259 #
786 # The crash occurs during a sync() of file $crashfile. When the crash 1260 # The crash occurs during a sync() of file $crashfile. When the crash
787 # occurs a random subset of all unsynced writes made by the process are 1261 # occurs a random subset of all unsynced writes made by the process are
788 # written into the files on disk. Argument $crashdelay indicates the 1262 # written into the files on disk. Argument $crashdelay indicates the
789 # number of file syncs to wait before crashing. 1263 # number of file syncs to wait before crashing.
790 # 1264 #
791 # The return value is a list of two elements. The first element is a 1265 # The return value is a list of two elements. The first element is a
792 # boolean, indicating whether or not the process actually crashed or 1266 # boolean, indicating whether or not the process actually crashed or
793 # reported some other error. The second element in the returned list is the 1267 # reported some other error. The second element in the returned list is the
794 # error message. This is "child process exited abnormally" if the crash 1268 # error message. This is "child process exited abnormally" if the crash
795 # occured. 1269 # occurred.
796 # 1270 #
797 # crashsql -delay CRASHDELAY -file CRASHFILE ?-blocksize BLOCKSIZE? $sql 1271 # crashsql -delay CRASHDELAY -file CRASHFILE ?-blocksize BLOCKSIZE? $sql
798 # 1272 #
799 proc crashsql {args} { 1273 proc crashsql {args} {
800 1274
801 set blocksize "" 1275 set blocksize ""
802 set crashdelay 1 1276 set crashdelay 1
803 set prngseed 0 1277 set prngseed 0
1278 set opendb { sqlite3 db test.db -vfs crash }
804 set tclbody {} 1279 set tclbody {}
805 set crashfile "" 1280 set crashfile ""
806 set dc "" 1281 set dc ""
807 set sql [lindex $args end] 1282 set sql [lindex $args end]
808 1283
809 for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} { 1284 for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} {
810 set z [lindex $args $ii] 1285 set z [lindex $args $ii]
811 set n [string length $z] 1286 set n [string length $z]
812 set z2 [lindex $args [expr $ii+1]] 1287 set z2 [lindex $args [expr $ii+1]]
813 1288
814 if {$n>1 && [string first $z -delay]==0} {set crashdelay $z2} \ 1289 if {$n>1 && [string first $z -delay]==0} {set crashdelay $z2} \
1290 elseif {$n>1 && [string first $z -opendb]==0} {set opendb $z2} \
815 elseif {$n>1 && [string first $z -seed]==0} {set prngseed $z2} \ 1291 elseif {$n>1 && [string first $z -seed]==0} {set prngseed $z2} \
816 elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \ 1292 elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \
817 elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \ 1293 elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \
818 elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \ 1294 elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \
819 elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" } \ 1295 elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" } \
820 else { error "Unrecognized option: $z" } 1296 else { error "Unrecognized option: $z" }
821 } 1297 }
822 1298
823 if {$crashfile eq ""} { 1299 if {$crashfile eq ""} {
824 error "Compulsory option -file missing" 1300 error "Compulsory option -file missing"
825 } 1301 }
826 1302
827 # $crashfile gets compared to the native filename in 1303 # $crashfile gets compared to the native filename in
828 # cfSync(), which can be different then what TCL uses by 1304 # cfSync(), which can be different then what TCL uses by
829 # default, so here we force it to the "nativename" format. 1305 # default, so here we force it to the "nativename" format.
830 set cfile [string map {\\ \\\\} [file nativename [file join [pwd] $crashfile]] ] 1306 set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfi le]]]
831 1307
832 set f [open crash.tcl w] 1308 set f [open crash.tcl w]
833 puts $f "sqlite3_crash_enable 1" 1309 puts $f "sqlite3_crash_enable 1"
834 puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile" 1310 puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile"
835 puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte" 1311 puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
836 puts $f "sqlite3 db test.db -vfs crash" 1312 puts $f $opendb
837 1313
838 # This block sets the cache size of the main database to 10 1314 # This block sets the cache size of the main database to 10
839 # pages. This is done in case the build is configured to omit 1315 # pages. This is done in case the build is configured to omit
840 # "PRAGMA cache_size". 1316 # "PRAGMA cache_size".
841 puts $f {db eval {SELECT * FROM sqlite_master;}} 1317 puts $f {db eval {SELECT * FROM sqlite_master;}}
842 puts $f {set bt [btree_from_db db]} 1318 puts $f {set bt [btree_from_db db]}
843 puts $f {btree_set_cache_size $bt 10} 1319 puts $f {btree_set_cache_size $bt 10}
1320
844 if {$prngseed} { 1321 if {$prngseed} {
845 set seed [expr {$prngseed%10007+1}] 1322 set seed [expr {$prngseed%10007+1}]
846 # puts seed=$seed 1323 # puts seed=$seed
847 puts $f "db eval {SELECT randomblob($seed)}" 1324 puts $f "db eval {SELECT randomblob($seed)}"
848 } 1325 }
849 1326
850 if {[string length $tclbody]>0} { 1327 if {[string length $tclbody]>0} {
851 puts $f $tclbody 1328 puts $f $tclbody
852 } 1329 }
853 if {[string length $sql]>0} { 1330 if {[string length $sql]>0} {
854 puts $f "db eval {" 1331 puts $f "db eval {"
855 puts $f "$sql" 1332 puts $f "$sql"
856 puts $f "}" 1333 puts $f "}"
857 } 1334 }
858 close $f 1335 close $f
859 set r [catch { 1336 set r [catch {
860 exec [info nameofexec] crash.tcl >@stdout 1337 exec [info nameofexec] crash.tcl >@stdout
861 } msg] 1338 } msg]
862 1339
863 # Windows/ActiveState TCL returns a slightly different 1340 # Windows/ActiveState TCL returns a slightly different
864 # error message. We map that to the expected message 1341 # error message. We map that to the expected message
865 # so that we don't have to change all of the test 1342 # so that we don't have to change all of the test
866 # cases. 1343 # cases.
867 if {$::tcl_platform(platform)=="windows"} { 1344 if {$::tcl_platform(platform)=="windows"} {
868 if {$msg=="child killed: unknown signal"} { 1345 if {$msg=="child killed: unknown signal"} {
869 set msg "child process exited abnormally" 1346 set msg "child process exited abnormally"
870 } 1347 }
871 } 1348 }
872 1349
873 lappend r $msg 1350 lappend r $msg
874 } 1351 }
875 1352
1353 proc run_ioerr_prep {} {
1354 set ::sqlite_io_error_pending 0
1355 catch {db close}
1356 catch {db2 close}
1357 catch {forcedelete test.db}
1358 catch {forcedelete test.db-journal}
1359 catch {forcedelete test2.db}
1360 catch {forcedelete test2.db-journal}
1361 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
1362 sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
1363 if {[info exists ::ioerropts(-tclprep)]} {
1364 eval $::ioerropts(-tclprep)
1365 }
1366 if {[info exists ::ioerropts(-sqlprep)]} {
1367 execsql $::ioerropts(-sqlprep)
1368 }
1369 expr 0
1370 }
1371
876 # Usage: do_ioerr_test <test number> <options...> 1372 # Usage: do_ioerr_test <test number> <options...>
877 # 1373 #
878 # This proc is used to implement test cases that check that IO errors 1374 # This proc is used to implement test cases that check that IO errors
879 # are correctly handled. The first argument, <test number>, is an integer 1375 # are correctly handled. The first argument, <test number>, is an integer
880 # used to name the tests executed by this proc. Options are as follows: 1376 # used to name the tests executed by this proc. Options are as follows:
881 # 1377 #
882 # -tclprep TCL script to run to prepare test. 1378 # -tclprep TCL script to run to prepare test.
883 # -sqlprep SQL script to run to prepare test. 1379 # -sqlprep SQL script to run to prepare test.
884 # -tclbody TCL script to run with IO error simulation. 1380 # -tclbody TCL script to run with IO error simulation.
885 # -sqlbody TCL script to run with IO error simulation. 1381 # -sqlbody TCL script to run with IO error simulation.
886 # -exclude List of 'N' values not to test. 1382 # -exclude List of 'N' values not to test.
887 # -erc Use extended result codes 1383 # -erc Use extended result codes
888 # -persist Make simulated I/O errors persistent 1384 # -persist Make simulated I/O errors persistent
889 # -start Value of 'N' to begin with (default 1) 1385 # -start Value of 'N' to begin with (default 1)
890 # 1386 #
891 # -cksum Boolean. If true, test that the database does 1387 # -cksum Boolean. If true, test that the database does
892 # not change during the execution of the test case. 1388 # not change during the execution of the test case.
893 # 1389 #
894 proc do_ioerr_test {testname args} { 1390 proc do_ioerr_test {testname args} {
895 1391
896 set ::ioerropts(-start) 1 1392 set ::ioerropts(-start) 1
897 set ::ioerropts(-cksum) 0 1393 set ::ioerropts(-cksum) 0
898 set ::ioerropts(-erc) 0 1394 set ::ioerropts(-erc) 0
899 set ::ioerropts(-count) 100000000 1395 set ::ioerropts(-count) 100000000
900 set ::ioerropts(-persist) 1 1396 set ::ioerropts(-persist) 1
901 set ::ioerropts(-ckrefcount) 0 1397 set ::ioerropts(-ckrefcount) 0
902 set ::ioerropts(-restoreprng) 1 1398 set ::ioerropts(-restoreprng) 1
903 array set ::ioerropts $args 1399 array set ::ioerropts $args
904 1400
905 # TEMPORARY: For 3.5.9, disable testing of extended result codes. There are 1401 # TEMPORARY: For 3.5.9, disable testing of extended result codes. There are
906 # a couple of obscure IO errors that do not return them. 1402 # a couple of obscure IO errors that do not return them.
907 set ::ioerropts(-erc) 0 1403 set ::ioerropts(-erc) 0
908 1404
1405 # Create a single TCL script from the TCL and SQL specified
1406 # as the body of the test.
1407 set ::ioerrorbody {}
1408 if {[info exists ::ioerropts(-tclbody)]} {
1409 append ::ioerrorbody "$::ioerropts(-tclbody)\n"
1410 }
1411 if {[info exists ::ioerropts(-sqlbody)]} {
1412 append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}"
1413 }
1414
1415 save_prng_state
1416 if {$::ioerropts(-cksum)} {
1417 run_ioerr_prep
1418 eval $::ioerrorbody
1419 set ::goodcksum [cksum]
1420 }
1421
909 set ::go 1 1422 set ::go 1
910 #reset_prng_state 1423 #reset_prng_state
911 save_prng_state
912 for {set n $::ioerropts(-start)} {$::go} {incr n} { 1424 for {set n $::ioerropts(-start)} {$::go} {incr n} {
913 set ::TN $n 1425 set ::TN $n
914 incr ::ioerropts(-count) -1 1426 incr ::ioerropts(-count) -1
915 if {$::ioerropts(-count)<0} break 1427 if {$::ioerropts(-count)<0} break
916 1428
917 # Skip this IO error if it was specified with the "-exclude" option. 1429 # Skip this IO error if it was specified with the "-exclude" option.
918 if {[info exists ::ioerropts(-exclude)]} { 1430 if {[info exists ::ioerropts(-exclude)]} {
919 if {[lsearch $::ioerropts(-exclude) $n]!=-1} continue 1431 if {[lsearch $::ioerropts(-exclude) $n]!=-1} continue
920 } 1432 }
921 if {$::ioerropts(-restoreprng)} { 1433 if {$::ioerropts(-restoreprng)} {
922 restore_prng_state 1434 restore_prng_state
923 } 1435 }
924 1436
925 # Delete the files test.db and test2.db, then execute the TCL and 1437 # Delete the files test.db and test2.db, then execute the TCL and
926 # SQL (in that order) to prepare for the test case. 1438 # SQL (in that order) to prepare for the test case.
927 do_test $testname.$n.1 { 1439 do_test $testname.$n.1 {
928 set ::sqlite_io_error_pending 0 1440 run_ioerr_prep
929 catch {db close}
930 catch {db2 close}
931 catch {file delete -force test.db}
932 catch {file delete -force test.db-journal}
933 catch {file delete -force test2.db}
934 catch {file delete -force test2.db-journal}
935 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
936 sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
937 if {[info exists ::ioerropts(-tclprep)]} {
938 eval $::ioerropts(-tclprep)
939 }
940 if {[info exists ::ioerropts(-sqlprep)]} {
941 execsql $::ioerropts(-sqlprep)
942 }
943 expr 0
944 } {0} 1441 } {0}
945 1442
946 # Read the 'checksum' of the database. 1443 # Read the 'checksum' of the database.
947 if {$::ioerropts(-cksum)} { 1444 if {$::ioerropts(-cksum)} {
948 set checksum [cksum] 1445 set ::checksum [cksum]
949 } 1446 }
950 1447
951 # Set the Nth IO error to fail. 1448 # Set the Nth IO error to fail.
952 do_test $testname.$n.2 [subst { 1449 do_test $testname.$n.2 [subst {
953 set ::sqlite_io_error_persist $::ioerropts(-persist) 1450 set ::sqlite_io_error_persist $::ioerropts(-persist)
954 set ::sqlite_io_error_pending $n 1451 set ::sqlite_io_error_pending $n
955 }] $n 1452 }] $n
956
957 # Create a single TCL script from the TCL and SQL specified
958 # as the body of the test.
959 set ::ioerrorbody {}
960 if {[info exists ::ioerropts(-tclbody)]} {
961 append ::ioerrorbody "$::ioerropts(-tclbody)\n"
962 }
963 if {[info exists ::ioerropts(-sqlbody)]} {
964 append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}"
965 }
966 1453
967 # Execute the TCL Script created in the above block. If 1454 # Execute the TCL script created for the body of this test. If
968 # there are at least N IO operations performed by SQLite as 1455 # at least N IO operations performed by SQLite as a result of
969 # a result of the script, the Nth will fail. 1456 # the script, the Nth will fail.
970 do_test $testname.$n.3 { 1457 do_test $testname.$n.3 {
971 set ::sqlite_io_error_hit 0 1458 set ::sqlite_io_error_hit 0
972 set ::sqlite_io_error_hardhit 0 1459 set ::sqlite_io_error_hardhit 0
973 set r [catch $::ioerrorbody msg] 1460 set r [catch $::ioerrorbody msg]
974 set ::errseen $r 1461 set ::errseen $r
975 set rc [sqlite3_errcode $::DB] 1462 set rc [sqlite3_errcode $::DB]
976 if {$::ioerropts(-erc)} { 1463 if {$::ioerropts(-erc)} {
977 # If we are in extended result code mode, make sure all of the 1464 # If we are in extended result code mode, make sure all of the
978 # IOERRs we get back really do have their extended code values. 1465 # IOERRs we get back really do have their extended code values.
979 # If an extended result code is returned, the sqlite3_errcode 1466 # If an extended result code is returned, the sqlite3_errcode
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 # 1. We never hit the IO error and the SQL returned OK 1499 # 1. We never hit the IO error and the SQL returned OK
1013 # 2. An IO error was hit and the SQL failed 1500 # 2. An IO error was hit and the SQL failed
1014 # 1501 #
1015 #puts "s=$s r=$r q=$q" 1502 #puts "s=$s r=$r q=$q"
1016 expr { ($s && !$r && !$q) || (!$s && $r && $q) } 1503 expr { ($s && !$r && !$q) || (!$s && $r && $q) }
1017 } {1} 1504 } {1}
1018 1505
1019 set ::sqlite_io_error_hit 0 1506 set ::sqlite_io_error_hit 0
1020 set ::sqlite_io_error_pending 0 1507 set ::sqlite_io_error_pending 0
1021 1508
1022 # Check that no page references were leaked. There should be 1509 # Check that no page references were leaked. There should be
1023 # a single reference if there is still an active transaction, 1510 # a single reference if there is still an active transaction,
1024 # or zero otherwise. 1511 # or zero otherwise.
1025 # 1512 #
1026 # UPDATE: If the IO error occurs after a 'BEGIN' but before any 1513 # UPDATE: If the IO error occurs after a 'BEGIN' but before any
1027 # locks are established on database files (i.e. if the error 1514 # locks are established on database files (i.e. if the error
1028 # occurs while attempting to detect a hot-journal file), then 1515 # occurs while attempting to detect a hot-journal file), then
1029 # there may 0 page references and an active transaction according 1516 # there may 0 page references and an active transaction according
1030 # to [sqlite3_get_autocommit]. 1517 # to [sqlite3_get_autocommit].
1031 # 1518 #
1032 if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-ckrefcount)} { 1519 if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-ckrefcount)} {
1033 do_test $testname.$n.4 { 1520 do_test $testname.$n.4 {
1034 set bt [btree_from_db db] 1521 set bt [btree_from_db db]
1035 db_enter db 1522 db_enter db
1036 array set stats [btree_pager_stats $bt] 1523 array set stats [btree_pager_stats $bt]
1037 db_leave db 1524 db_leave db
1038 set nRef $stats(ref) 1525 set nRef $stats(ref)
1039 expr {$nRef == 0 || ([sqlite3_get_autocommit db]==0 && $nRef == 1)} 1526 expr {$nRef == 0 || ([sqlite3_get_autocommit db]==0 && $nRef == 1)}
1040 } {1} 1527 } {1}
1041 } 1528 }
1042 1529
1043 # If there is an open database handle and no open transaction, 1530 # If there is an open database handle and no open transaction,
1044 # and the pager is not running in exclusive-locking mode, 1531 # and the pager is not running in exclusive-locking mode,
1045 # check that the pager is in "unlocked" state. Theoretically, 1532 # check that the pager is in "unlocked" state. Theoretically,
1046 # if a call to xUnlock() failed due to an IO error the underlying 1533 # if a call to xUnlock() failed due to an IO error the underlying
1047 # file may still be locked. 1534 # file may still be locked.
1048 # 1535 #
1049 ifcapable pragma { 1536 ifcapable pragma {
1050 if { [info commands db] ne "" 1537 if { [info commands db] ne ""
1051 && $::ioerropts(-ckrefcount) 1538 && $::ioerropts(-ckrefcount)
1052 && [db one {pragma locking_mode}] eq "normal" 1539 && [db one {pragma locking_mode}] eq "normal"
1053 && [sqlite3_get_autocommit db] 1540 && [sqlite3_get_autocommit db]
1054 } { 1541 } {
1055 do_test $testname.$n.5 { 1542 do_test $testname.$n.5 {
1056 set bt [btree_from_db db] 1543 set bt [btree_from_db db]
1057 db_enter db 1544 db_enter db
1058 array set stats [btree_pager_stats $bt] 1545 array set stats [btree_pager_stats $bt]
1059 db_leave db 1546 db_leave db
1060 set stats(state) 1547 set stats(state)
1061 } 0 1548 } 0
1062 } 1549 }
1063 } 1550 }
1064 1551
1065 # If an IO error occured, then the checksum of the database should 1552 # If an IO error occurred, then the checksum of the database should
1066 # be the same as before the script that caused the IO error was run. 1553 # be the same as before the script that caused the IO error was run.
1067 # 1554 #
1068 if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-cksum)} { 1555 if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-cksum)} {
1069 do_test $testname.$n.6 { 1556 do_test $testname.$n.6 {
1070 catch {db close} 1557 catch {db close}
1071 catch {db2 close} 1558 catch {db2 close}
1072 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] 1559 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
1073 cksum 1560 set nowcksum [cksum]
1074 } $checksum 1561 set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}]
1562 if {$res==0} {
1563 puts "now=$nowcksum"
1564 puts "the=$::checksum"
1565 puts "fwd=$::goodcksum"
1566 }
1567 set res
1568 } 1
1075 } 1569 }
1076 1570
1077 set ::sqlite_io_error_hardhit 0 1571 set ::sqlite_io_error_hardhit 0
1078 set ::sqlite_io_error_pending 0 1572 set ::sqlite_io_error_pending 0
1079 if {[info exists ::ioerropts(-cleanup)]} { 1573 if {[info exists ::ioerropts(-cleanup)]} {
1080 catch $::ioerropts(-cleanup) 1574 catch $::ioerropts(-cleanup)
1081 } 1575 }
1082 } 1576 }
1083 set ::sqlite_io_error_pending 0 1577 set ::sqlite_io_error_pending 0
1084 set ::sqlite_io_error_persist 0 1578 set ::sqlite_io_error_persist 0
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1130 append txt [$db eval "SELECT * FROM $tbl"] 1624 append txt [$db eval "SELECT * FROM $tbl"]
1131 } 1625 }
1132 foreach prag {default_cache_size} { 1626 foreach prag {default_cache_size} {
1133 append txt $prag-[$db eval "PRAGMA $prag"]\n 1627 append txt $prag-[$db eval "PRAGMA $prag"]\n
1134 } 1628 }
1135 # puts txt=$txt 1629 # puts txt=$txt
1136 return [md5 $txt] 1630 return [md5 $txt]
1137 } 1631 }
1138 1632
1139 # Generate a checksum based on the contents of a single database with 1633 # Generate a checksum based on the contents of a single database with
1140 # a database connection. The name of the database is $dbname. 1634 # a database connection. The name of the database is $dbname.
1141 # Examples of $dbname are "temp" or "main". 1635 # Examples of $dbname are "temp" or "main".
1142 # 1636 #
1143 proc dbcksum {db dbname} { 1637 proc dbcksum {db dbname} {
1144 if {$dbname=="temp"} { 1638 if {$dbname=="temp"} {
1145 set master sqlite_temp_master 1639 set master sqlite_temp_master
1146 } else { 1640 } else {
1147 set master $dbname.sqlite_master 1641 set master $dbname.sqlite_master
1148 } 1642 }
1149 set alltab [$db eval "SELECT name FROM $master WHERE type='table'"] 1643 set alltab [$db eval "SELECT name FROM $master WHERE type='table'"]
1150 set txt [$db eval "SELECT * FROM $master"]\n 1644 set txt [$db eval "SELECT * FROM $master"]\n
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 } 1692 }
1199 set contents [string map {' ''} $contents] 1693 set contents [string map {' ''} $contents]
1200 append sql "INSERT INTO ${database}.file VALUES('$f', '$contents');\n" 1694 append sql "INSERT INTO ${database}.file VALUES('$f', '$contents');\n"
1201 } 1695 }
1202 1696
1203 set fd [open $filename w] 1697 set fd [open $filename w]
1204 puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;" 1698 puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
1205 close $fd 1699 close $fd
1206 } 1700 }
1207 1701
1208 # Copy file $from into $to. This is used because some versions of
1209 # TCL for windows (notably the 8.4.1 binary package shipped with the
1210 # current mingw release) have a broken "file copy" command.
1211 #
1212 proc copy_file {from to} {
1213 if {$::tcl_platform(platform)=="unix"} {
1214 file copy -force $from $to
1215 } else {
1216 set f [open $from]
1217 fconfigure $f -translation binary
1218 set t [open $to w]
1219 fconfigure $t -translation binary
1220 puts -nonewline $t [read $f [file size $from]]
1221 close $t
1222 close $f
1223 }
1224 }
1225
1226 # Drop all tables in database [db] 1702 # Drop all tables in database [db]
1227 proc drop_all_tables {{db db}} { 1703 proc drop_all_tables {{db db}} {
1228 ifcapable trigger&&foreignkey { 1704 ifcapable trigger&&foreignkey {
1229 set pk [$db one "PRAGMA foreign_keys"] 1705 set pk [$db one "PRAGMA foreign_keys"]
1230 $db eval "PRAGMA foreign_keys = OFF" 1706 $db eval "PRAGMA foreign_keys = OFF"
1231 } 1707 }
1232 foreach {idx name file} [db eval {PRAGMA database_list}] { 1708 foreach {idx name file} [db eval {PRAGMA database_list}] {
1233 if {$idx==1} { 1709 if {$idx==1} {
1234 set master sqlite_temp_master 1710 set master sqlite_temp_master
1235 } else { 1711 } else {
1236 set master $name.sqlite_master 1712 set master $name.sqlite_master
1237 } 1713 }
1238 foreach {t type} [$db eval " 1714 foreach {t type} [$db eval "
1239 SELECT name, type FROM $master 1715 SELECT name, type FROM $master
1240 WHERE type IN('table', 'view') AND name NOT LIKE 'sqliteX_%' ESCAPE 'X' 1716 WHERE type IN('table', 'view') AND name NOT LIKE 'sqliteX_%' ESCAPE 'X'
1241 "] { 1717 "] {
1242 $db eval "DROP $type \"$t\"" 1718 $db eval "DROP $type \"$t\""
1243 } 1719 }
1244 } 1720 }
1245 ifcapable trigger&&foreignkey { 1721 ifcapable trigger&&foreignkey {
1246 $db eval "PRAGMA foreign_keys = $pk" 1722 $db eval "PRAGMA foreign_keys = $pk"
1247 } 1723 }
1248 } 1724 }
1249 1725
1250 #------------------------------------------------------------------------- 1726 #-------------------------------------------------------------------------
1251 # If a test script is executed with global variable $::G(perm:name) set to 1727 # If a test script is executed with global variable $::G(perm:name) set to
1252 # "wal", then the tests are run in WAL mode. Otherwise, they should be run 1728 # "wal", then the tests are run in WAL mode. Otherwise, they should be run
1253 # in rollback mode. The following Tcl procs are used to make this less 1729 # in rollback mode. The following Tcl procs are used to make this less
1254 # intrusive: 1730 # intrusive:
1255 # 1731 #
1256 # wal_set_journal_mode ?DB? 1732 # wal_set_journal_mode ?DB?
1257 # 1733 #
1258 # If running a WAL test, execute "PRAGMA journal_mode = wal" using 1734 # If running a WAL test, execute "PRAGMA journal_mode = wal" using
1259 # connection handle DB. Otherwise, this command is a no-op. 1735 # connection handle DB. Otherwise, this command is a no-op.
1260 # 1736 #
1261 # wal_check_journal_mode TESTNAME ?DB? 1737 # wal_check_journal_mode TESTNAME ?DB?
1262 # 1738 #
1263 # If running a WAL test, execute a tests case that fails if the main 1739 # If running a WAL test, execute a tests case that fails if the main
1264 # database for connection handle DB is not currently a WAL database. 1740 # database for connection handle DB is not currently a WAL database.
1265 # Otherwise (if not running a WAL permutation) this is a no-op. 1741 # Otherwise (if not running a WAL permutation) this is a no-op.
1266 # 1742 #
1267 # wal_is_wal_mode 1743 # wal_is_wal_mode
1268 # 1744 #
1269 # Returns true if this test should be run in WAL mode. False otherwise. 1745 # Returns true if this test should be run in WAL mode. False otherwise.
1270 # 1746 #
1271 proc wal_is_wal_mode {} { 1747 proc wal_is_wal_mode {} {
1272 expr {[permutation] eq "wal"} 1748 expr {[permutation] eq "wal"}
1273 } 1749 }
1274 proc wal_set_journal_mode {{db db}} { 1750 proc wal_set_journal_mode {{db db}} {
1275 if { [wal_is_wal_mode] } { 1751 if { [wal_is_wal_mode] } {
1276 $db eval "PRAGMA journal_mode = WAL" 1752 $db eval "PRAGMA journal_mode = WAL"
1277 } 1753 }
1278 } 1754 }
1279 proc wal_check_journal_mode {testname {db db}} { 1755 proc wal_check_journal_mode {testname {db db}} {
1280 if { [wal_is_wal_mode] } { 1756 if { [wal_is_wal_mode] } {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1361 1837
1362 # Test that all files opened by the test script were closed. Omit this 1838 # Test that all files opened by the test script were closed. Omit this
1363 # if the test script has "thread" in its name. The open file counter 1839 # if the test script has "thread" in its name. The open file counter
1364 # is not thread-safe. 1840 # is not thread-safe.
1365 # 1841 #
1366 if {[info exists ::run_thread_tests_called]==0} { 1842 if {[info exists ::run_thread_tests_called]==0} {
1367 do_test ${tail}-closeallfiles { expr {$::sqlite_open_file_count>0} } {0} 1843 do_test ${tail}-closeallfiles { expr {$::sqlite_open_file_count>0} } {0}
1368 } 1844 }
1369 set ::sqlite_open_file_count 0 1845 set ::sqlite_open_file_count 0
1370 1846
1371 # Test that the global "shared-cache" setting was not altered by 1847 # Test that the global "shared-cache" setting was not altered by
1372 # the test script. 1848 # the test script.
1373 # 1849 #
1374 ifcapable shared_cache { 1850 ifcapable shared_cache {
1375 set res [expr {[sqlite3_enable_shared_cache] == $scs}] 1851 set res [expr {[sqlite3_enable_shared_cache] == $scs}]
1376 do_test ${tail}-sharedcachesetting [list set {} $res] 1 1852 do_test ${tail}-sharedcachesetting [list set {} $res] 1
1377 } 1853 }
1378 1854
1379 # Add some info to the output. 1855 # Add some info to the output.
1380 # 1856 #
1381 puts "Time: $tail $ms ms" 1857 puts "Time: $tail $ms ms"
1382 show_memstats 1858 show_memstats
1383 } 1859 }
1384 1860
(...skipping 12 matching lines...) Expand all
1397 db36231 close 1873 db36231 close
1398 hexio_write test.db 28 $A 1874 hexio_write test.db 28 $A
1399 hexio_write test.db 92 $B 1875 hexio_write test.db 92 $B
1400 return "" 1876 return ""
1401 } 1877 }
1402 1878
1403 proc db_save {} { 1879 proc db_save {} {
1404 foreach f [glob -nocomplain sv_test.db*] { forcedelete $f } 1880 foreach f [glob -nocomplain sv_test.db*] { forcedelete $f }
1405 foreach f [glob -nocomplain test.db*] { 1881 foreach f [glob -nocomplain test.db*] {
1406 set f2 "sv_$f" 1882 set f2 "sv_$f"
1407 file copy -force $f $f2 1883 forcecopy $f $f2
1408 } 1884 }
1409 } 1885 }
1410 proc db_save_and_close {} { 1886 proc db_save_and_close {} {
1411 db_save 1887 db_save
1412 catch { db close } 1888 catch { db close }
1413 return "" 1889 return ""
1414 } 1890 }
1415 proc db_restore {} { 1891 proc db_restore {} {
1416 foreach f [glob -nocomplain test.db*] { forcedelete $f } 1892 foreach f [glob -nocomplain test.db*] { forcedelete $f }
1417 foreach f2 [glob -nocomplain sv_test.db*] { 1893 foreach f2 [glob -nocomplain sv_test.db*] {
1418 set f [string range $f2 3 end] 1894 set f [string range $f2 3 end]
1419 file copy -force $f2 $f 1895 forcecopy $f2 $f
1420 } 1896 }
1421 } 1897 }
1422 proc db_restore_and_reopen {{dbfile test.db}} { 1898 proc db_restore_and_reopen {{dbfile test.db}} {
1423 catch { db close } 1899 catch { db close }
1424 db_restore 1900 db_restore
1425 sqlite3 db $dbfile 1901 sqlite3 db $dbfile
1426 } 1902 }
1427 proc db_delete_and_reopen {{file test.db}} { 1903 proc db_delete_and_reopen {{file test.db}} {
1428 catch { db close } 1904 catch { db close }
1429 foreach f [glob -nocomplain test.db*] { file delete -force $f } 1905 foreach f [glob -nocomplain test.db*] { forcedelete $f }
1430 sqlite3 db $file 1906 sqlite3 db $file
1431 } 1907 }
1432 1908
1433 # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set 1909 # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set
1434 # to non-zero, then set the global variable $AUTOVACUUM to 1. 1910 # to non-zero, then set the global variable $AUTOVACUUM to 1.
1435 set AUTOVACUUM $sqlite_options(default_autovacuum) 1911 set AUTOVACUUM $sqlite_options(default_autovacuum)
1436 1912
1913 # Make sure the FTS enhanced query syntax is disabled.
1914 set sqlite_fts3_enable_parentheses 0
1915
1916 # During testing, assume that all database files are well-formed. The
1917 # few test cases that deliberately corrupt database files should rescind
1918 # this setting by invoking "database_can_be_corrupt"
1919 #
1920 database_never_corrupt
1921
1437 source $testdir/thread_common.tcl 1922 source $testdir/thread_common.tcl
1438 source $testdir/malloc_common.tcl 1923 source $testdir/malloc_common.tcl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698