PageRenderTime 772ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/test/tester.tcl

https://bitbucket.org/aware/sqlite
TCL | 1651 lines | 1258 code | 89 blank | 304 comment | 131 complexity | 130e91ac98c7f42f7cd53707dea36c21 MD5 | raw file
  1. # 2001 September 15
  2. #
  3. # The author disclaims copyright to this source code. In place of
  4. # a legal notice, here is a blessing:
  5. #
  6. # May you do good and not evil.
  7. # May you find forgiveness for yourself and forgive others.
  8. # May you share freely, never taking more than you give.
  9. #
  10. #***********************************************************************
  11. # This file implements some common TCL routines used for regression
  12. # testing the SQLite library
  13. #
  14. # $Id:$
  15. #-------------------------------------------------------------------------
  16. # The commands provided by the code in this file to help with creating
  17. # test cases are as follows:
  18. #
  19. # Commands to manipulate the db and the file-system at a high level:
  20. #
  21. # is_relative_file
  22. # test_pwd
  23. # get_pwd
  24. # copy_file FROM TO
  25. # delete_file FILENAME
  26. # drop_all_tables ?DB?
  27. # forcecopy FROM TO
  28. # forcedelete FILENAME
  29. #
  30. # Test the capability of the SQLite version built into the interpreter to
  31. # determine if a specific test can be run:
  32. #
  33. # ifcapable EXPR
  34. #
  35. # Calulate checksums based on database contents:
  36. #
  37. # dbcksum DB DBNAME
  38. # allcksum ?DB?
  39. # cksum ?DB?
  40. #
  41. # Commands to execute/explain SQL statements:
  42. #
  43. # stepsql DB SQL
  44. # execsql2 SQL
  45. # explain_no_trace SQL
  46. # explain SQL ?DB?
  47. # catchsql SQL ?DB?
  48. # execsql SQL ?DB?
  49. #
  50. # Commands to run test cases:
  51. #
  52. # do_ioerr_test TESTNAME ARGS...
  53. # crashsql ARGS...
  54. # integrity_check TESTNAME ?DB?
  55. # do_test TESTNAME SCRIPT EXPECTED
  56. # do_execsql_test TESTNAME SQL EXPECTED
  57. # do_catchsql_test TESTNAME SQL EXPECTED
  58. #
  59. # Commands providing a lower level interface to the global test counters:
  60. #
  61. # set_test_counter COUNTER ?VALUE?
  62. # omit_test TESTNAME REASON ?APPEND?
  63. # fail_test TESTNAME
  64. # incr_ntest
  65. #
  66. # Command run at the end of each test file:
  67. #
  68. # finish_test
  69. #
  70. # Commands to help create test files that run with the "WAL" and other
  71. # permutations (see file permutations.test):
  72. #
  73. # wal_is_wal_mode
  74. # wal_set_journal_mode ?DB?
  75. # wal_check_journal_mode TESTNAME?DB?
  76. # permutation
  77. # presql
  78. #
  79. # Set the precision of FP arithmatic used by the interpreter. And
  80. # configure SQLite to take database file locks on the page that begins
  81. # 64KB into the database file instead of the one 1GB in. This means
  82. # the code that handles that special case can be tested without creating
  83. # very large database files.
  84. #
  85. set tcl_precision 15
  86. sqlite3_test_control_pending_byte 0x0010000
  87. # If the pager codec is available, create a wrapper for the [sqlite3]
  88. # command that appends "-key {xyzzy}" to the command line. i.e. this:
  89. #
  90. # sqlite3 db test.db
  91. #
  92. # becomes
  93. #
  94. # sqlite3 db test.db -key {xyzzy}
  95. #
  96. if {[info command sqlite_orig]==""} {
  97. rename sqlite3 sqlite_orig
  98. proc sqlite3 {args} {
  99. if {[llength $args]>=2 && [string index [lindex $args 0] 0]!="-"} {
  100. # This command is opening a new database connection.
  101. #
  102. if {[info exists ::G(perm:sqlite3_args)]} {
  103. set args [concat $args $::G(perm:sqlite3_args)]
  104. }
  105. if {[sqlite_orig -has-codec] && ![info exists ::do_not_use_codec]} {
  106. lappend args -key {xyzzy}
  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. if {[info exists ::G(perm:dbconfig)]} {
  113. set ::dbhandle [lindex $args 0]
  114. uplevel #0 $::G(perm:dbconfig)
  115. }
  116. set res
  117. } else {
  118. # This command is not opening a new database connection. Pass the
  119. # arguments through to the C implemenation as the are.
  120. #
  121. uplevel 1 sqlite_orig $args
  122. }
  123. }
  124. }
  125. proc getFileRetries {} {
  126. if {![info exists ::G(file-retries)]} {
  127. #
  128. # NOTE: Return the default number of retries for [file] operations. A
  129. # value of zero or less here means "disabled".
  130. #
  131. return [expr {$::tcl_platform(platform) eq "windows" ? 10 : 0}]
  132. }
  133. return $::G(file-retries)
  134. }
  135. proc getFileRetryDelay {} {
  136. if {![info exists ::G(file-retry-delay)]} {
  137. #
  138. # NOTE: Return the default number of milliseconds to wait when retrying
  139. # failed [file] operations. A value of zero or less means "do not
  140. # wait".
  141. #
  142. return 100; # TODO: Good default?
  143. }
  144. return $::G(file-retry-delay)
  145. }
  146. # Return the string representing the name of the current directory. On
  147. # Windows, the result is "normalized" to whatever our parent command shell
  148. # is using to prevent case-mismatch issues.
  149. #
  150. proc get_pwd {} {
  151. if {$::tcl_platform(platform) eq "windows"} {
  152. #
  153. # NOTE: Cannot use [file normalize] here because it would alter the
  154. # case of the result to what Tcl considers canonical, which would
  155. # defeat the purpose of this procedure.
  156. #
  157. return [string map [list \\ /] \
  158. [string trim [exec -- $::env(ComSpec) /c echo %CD%]]]
  159. } else {
  160. return [pwd]
  161. }
  162. }
  163. # Copy file $from into $to. This is used because some versions of
  164. # TCL for windows (notably the 8.4.1 binary package shipped with the
  165. # current mingw release) have a broken "file copy" command.
  166. #
  167. proc copy_file {from to} {
  168. do_copy_file false $from $to
  169. }
  170. proc forcecopy {from to} {
  171. do_copy_file true $from $to
  172. }
  173. proc do_copy_file {force from to} {
  174. set nRetry [getFileRetries] ;# Maximum number of retries.
  175. set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
  176. # On windows, sometimes even a [file copy -force] can fail. The cause is
  177. # usually "tag-alongs" - programs like anti-virus software, automatic backup
  178. # tools and various explorer extensions that keep a file open a little longer
  179. # than we expect, causing the delete to fail.
  180. #
  181. # The solution is to wait a short amount of time before retrying the copy.
  182. #
  183. if {$nRetry > 0} {
  184. for {set i 0} {$i<$nRetry} {incr i} {
  185. set rc [catch {
  186. if {$force} {
  187. file copy -force $from $to
  188. } else {
  189. file copy $from $to
  190. }
  191. } msg]
  192. if {$rc==0} break
  193. if {$nDelay > 0} { after $nDelay }
  194. }
  195. if {$rc} { error $msg }
  196. } else {
  197. if {$force} {
  198. file copy -force $from $to
  199. } else {
  200. file copy $from $to
  201. }
  202. }
  203. }
  204. # Check if a file name is relative
  205. #
  206. proc is_relative_file { file } {
  207. return [expr {[file pathtype $file] != "absolute"}]
  208. }
  209. # If the VFS supports using the current directory, returns [pwd];
  210. # otherwise, it returns only the provided suffix string (which is
  211. # empty by default).
  212. #
  213. proc test_pwd { args } {
  214. if {[llength $args] > 0} {
  215. set suffix1 [lindex $args 0]
  216. if {[llength $args] > 1} {
  217. set suffix2 [lindex $args 1]
  218. } else {
  219. set suffix2 $suffix1
  220. }
  221. } else {
  222. set suffix1 ""; set suffix2 ""
  223. }
  224. ifcapable curdir {
  225. return "[get_pwd]$suffix1"
  226. } else {
  227. return $suffix2
  228. }
  229. }
  230. # Delete a file or directory
  231. #
  232. proc delete_file {args} {
  233. do_delete_file false {*}$args
  234. }
  235. proc forcedelete {args} {
  236. do_delete_file true {*}$args
  237. }
  238. proc do_delete_file {force args} {
  239. set nRetry [getFileRetries] ;# Maximum number of retries.
  240. set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
  241. foreach filename $args {
  242. # On windows, sometimes even a [file delete -force] can fail just after
  243. # a file is closed. The cause is usually "tag-alongs" - programs like
  244. # anti-virus software, automatic backup tools and various explorer
  245. # extensions that keep a file open a little longer than we expect, causing
  246. # the delete to fail.
  247. #
  248. # The solution is to wait a short amount of time before retrying the
  249. # delete.
  250. #
  251. if {$nRetry > 0} {
  252. for {set i 0} {$i<$nRetry} {incr i} {
  253. set rc [catch {
  254. if {$force} {
  255. file delete -force $filename
  256. } else {
  257. file delete $filename
  258. }
  259. } msg]
  260. if {$rc==0} break
  261. if {$nDelay > 0} { after $nDelay }
  262. }
  263. if {$rc} { error $msg }
  264. } else {
  265. if {$force} {
  266. file delete -force $filename
  267. } else {
  268. file delete $filename
  269. }
  270. }
  271. }
  272. }
  273. proc execpresql {handle args} {
  274. trace remove execution $handle enter [list execpresql $handle]
  275. if {[info exists ::G(perm:presql)]} {
  276. $handle eval $::G(perm:presql)
  277. }
  278. }
  279. # This command should be called after loading tester.tcl from within
  280. # all test scripts that are incompatible with encryption codecs.
  281. #
  282. proc do_not_use_codec {} {
  283. set ::do_not_use_codec 1
  284. reset_db
  285. }
  286. # The following block only runs the first time this file is sourced. It
  287. # does not run in slave interpreters (since the ::cmdlinearg array is
  288. # populated before the test script is run in slave interpreters).
  289. #
  290. if {[info exists cmdlinearg]==0} {
  291. # Parse any options specified in the $argv array. This script accepts the
  292. # following options:
  293. #
  294. # --pause
  295. # --soft-heap-limit=NN
  296. # --maxerror=NN
  297. # --malloctrace=N
  298. # --backtrace=N
  299. # --binarylog=N
  300. # --soak=N
  301. # --file-retries=N
  302. # --file-retry-delay=N
  303. # --start=[$permutation:]$testfile
  304. # --match=$pattern
  305. #
  306. set cmdlinearg(soft-heap-limit) 0
  307. set cmdlinearg(maxerror) 1000
  308. set cmdlinearg(malloctrace) 0
  309. set cmdlinearg(backtrace) 10
  310. set cmdlinearg(binarylog) 0
  311. set cmdlinearg(soak) 0
  312. set cmdlinearg(file-retries) 0
  313. set cmdlinearg(file-retry-delay) 0
  314. set cmdlinearg(start) ""
  315. set cmdlinearg(match) ""
  316. set leftover [list]
  317. foreach a $argv {
  318. switch -regexp -- $a {
  319. {^-+pause$} {
  320. # Wait for user input before continuing. This is to give the user an
  321. # opportunity to connect profiling tools to the process.
  322. puts -nonewline "Press RETURN to begin..."
  323. flush stdout
  324. gets stdin
  325. }
  326. {^-+soft-heap-limit=.+$} {
  327. foreach {dummy cmdlinearg(soft-heap-limit)} [split $a =] break
  328. }
  329. {^-+maxerror=.+$} {
  330. foreach {dummy cmdlinearg(maxerror)} [split $a =] break
  331. }
  332. {^-+malloctrace=.+$} {
  333. foreach {dummy cmdlinearg(malloctrace)} [split $a =] break
  334. if {$cmdlinearg(malloctrace)} {
  335. sqlite3_memdebug_log start
  336. }
  337. }
  338. {^-+backtrace=.+$} {
  339. foreach {dummy cmdlinearg(backtrace)} [split $a =] break
  340. sqlite3_memdebug_backtrace $value
  341. }
  342. {^-+binarylog=.+$} {
  343. foreach {dummy cmdlinearg(binarylog)} [split $a =] break
  344. }
  345. {^-+soak=.+$} {
  346. foreach {dummy cmdlinearg(soak)} [split $a =] break
  347. set ::G(issoak) $cmdlinearg(soak)
  348. }
  349. {^-+file-retries=.+$} {
  350. foreach {dummy cmdlinearg(file-retries)} [split $a =] break
  351. set ::G(file-retries) $cmdlinearg(file-retries)
  352. }
  353. {^-+file-retry-delay=.+$} {
  354. foreach {dummy cmdlinearg(file-retry-delay)} [split $a =] break
  355. set ::G(file-retry-delay) $cmdlinearg(file-retry-delay)
  356. }
  357. {^-+start=.+$} {
  358. foreach {dummy cmdlinearg(start)} [split $a =] break
  359. set ::G(start:file) $cmdlinearg(start)
  360. if {[regexp {(.*):(.*)} $cmdlinearg(start) -> s.perm s.file]} {
  361. set ::G(start:permutation) ${s.perm}
  362. set ::G(start:file) ${s.file}
  363. }
  364. if {$::G(start:file) == ""} {unset ::G(start:file)}
  365. }
  366. {^-+match=.+$} {
  367. foreach {dummy cmdlinearg(match)} [split $a =] break
  368. set ::G(match) $cmdlinearg(match)
  369. if {$::G(match) == ""} {unset ::G(match)}
  370. }
  371. default {
  372. lappend leftover $a
  373. }
  374. }
  375. }
  376. set argv $leftover
  377. # Install the malloc layer used to inject OOM errors. And the 'automatic'
  378. # extensions. This only needs to be done once for the process.
  379. #
  380. sqlite3_shutdown
  381. install_malloc_faultsim 1
  382. sqlite3_initialize
  383. autoinstall_test_functions
  384. # If the --binarylog option was specified, create the logging VFS. This
  385. # call installs the new VFS as the default for all SQLite connections.
  386. #
  387. if {$cmdlinearg(binarylog)} {
  388. vfslog new binarylog {} vfslog.bin
  389. }
  390. # Set the backtrace depth, if malloc tracing is enabled.
  391. #
  392. if {$cmdlinearg(malloctrace)} {
  393. sqlite3_memdebug_backtrace $cmdlinearg(backtrace)
  394. }
  395. }
  396. # Update the soft-heap-limit each time this script is run. In that
  397. # way if an individual test file changes the soft-heap-limit, it
  398. # will be reset at the start of the next test file.
  399. #
  400. sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
  401. # Create a test database
  402. #
  403. proc reset_db {} {
  404. catch {db close}
  405. forcedelete test.db
  406. forcedelete test.db-journal
  407. forcedelete test.db-wal
  408. sqlite3 db ./test.db
  409. set ::DB [sqlite3_connection_pointer db]
  410. if {[info exists ::SETUP_SQL]} {
  411. db eval $::SETUP_SQL
  412. }
  413. }
  414. reset_db
  415. # Abort early if this script has been run before.
  416. #
  417. if {[info exists TC(count)]} return
  418. # Make sure memory statistics are enabled.
  419. #
  420. sqlite3_config_memstatus 1
  421. # Initialize the test counters and set up commands to access them.
  422. # Or, if this is a slave interpreter, set up aliases to write the
  423. # counters in the parent interpreter.
  424. #
  425. if {0==[info exists ::SLAVE]} {
  426. set TC(errors) 0
  427. set TC(count) 0
  428. set TC(fail_list) [list]
  429. set TC(omit_list) [list]
  430. proc set_test_counter {counter args} {
  431. if {[llength $args]} {
  432. set ::TC($counter) [lindex $args 0]
  433. }
  434. set ::TC($counter)
  435. }
  436. }
  437. # Record the fact that a sequence of tests were omitted.
  438. #
  439. proc omit_test {name reason {append 1}} {
  440. set omitList [set_test_counter omit_list]
  441. if {$append} {
  442. lappend omitList [list $name $reason]
  443. }
  444. set_test_counter omit_list $omitList
  445. }
  446. # Record the fact that a test failed.
  447. #
  448. proc fail_test {name} {
  449. set f [set_test_counter fail_list]
  450. lappend f $name
  451. set_test_counter fail_list $f
  452. set_test_counter errors [expr [set_test_counter errors] + 1]
  453. set nFail [set_test_counter errors]
  454. if {$nFail>=$::cmdlinearg(maxerror)} {
  455. puts "*** Giving up..."
  456. finalize_testing
  457. }
  458. }
  459. # Increment the number of tests run
  460. #
  461. proc incr_ntest {} {
  462. set_test_counter count [expr [set_test_counter count] + 1]
  463. }
  464. # Invoke the do_test procedure to run a single test
  465. #
  466. proc do_test {name cmd expected} {
  467. global argv cmdlinearg
  468. fix_testname name
  469. sqlite3_memdebug_settitle $name
  470. # if {[llength $argv]==0} {
  471. # set go 1
  472. # } else {
  473. # set go 0
  474. # foreach pattern $argv {
  475. # if {[string match $pattern $name]} {
  476. # set go 1
  477. # break
  478. # }
  479. # }
  480. # }
  481. if {[info exists ::G(perm:prefix)]} {
  482. set name "$::G(perm:prefix)$name"
  483. }
  484. incr_ntest
  485. puts -nonewline $name...
  486. flush stdout
  487. if {![info exists ::G(match)] || [string match $::G(match) $name]} {
  488. if {[catch {uplevel #0 "$cmd;\n"} result]} {
  489. puts "\nError: $result"
  490. fail_test $name
  491. } else {
  492. if {[regexp {^~?/.*/$} $expected]} {
  493. if {[string index $expected 0]=="~"} {
  494. set re [string range $expected 2 end-1]
  495. set ok [expr {![regexp $re $result]}]
  496. } else {
  497. set re [string range $expected 1 end-1]
  498. set ok [regexp $re $result]
  499. }
  500. } else {
  501. set ok [expr {[string compare $result $expected]==0}]
  502. }
  503. if {!$ok} {
  504. puts "\nExpected: \[$expected\]\n Got: \[$result\]"
  505. fail_test $name
  506. } else {
  507. puts " Ok"
  508. }
  509. }
  510. } else {
  511. puts " Omitted"
  512. omit_test $name "pattern mismatch" 0
  513. }
  514. flush stdout
  515. }
  516. proc catchcmd {db {cmd ""}} {
  517. global CLI
  518. set out [open cmds.txt w]
  519. puts $out $cmd
  520. close $out
  521. set line "exec $CLI $db < cmds.txt"
  522. set rc [catch { eval $line } msg]
  523. list $rc $msg
  524. }
  525. proc filepath_normalize {p} {
  526. # test cases should be written to assume "unix"-like file paths
  527. if {$::tcl_platform(platform)!="unix"} {
  528. # lreverse*2 as a hack to remove any unneeded {} after the string map
  529. lreverse [lreverse [string map {\\ /} [regsub -nocase -all {[a-z]:[/\\]+} $p {/}]]]
  530. } {
  531. set p
  532. }
  533. }
  534. proc do_filepath_test {name cmd expected} {
  535. uplevel [list do_test $name [
  536. subst -nocommands { filepath_normalize [ $cmd ] }
  537. ] [filepath_normalize $expected]]
  538. }
  539. proc realnum_normalize {r} {
  540. # different TCL versions display floating point values differently.
  541. string map {1.#INF inf Inf inf .0e e} [regsub -all {(e[+-])0+} $r {\1}]
  542. }
  543. proc do_realnum_test {name cmd expected} {
  544. uplevel [list do_test $name [
  545. subst -nocommands { realnum_normalize [ $cmd ] }
  546. ] [realnum_normalize $expected]]
  547. }
  548. proc fix_testname {varname} {
  549. upvar $varname testname
  550. if {[info exists ::testprefix]
  551. && [string is digit [string range $testname 0 0]]
  552. } {
  553. set testname "${::testprefix}-$testname"
  554. }
  555. }
  556. proc do_execsql_test {testname sql {result {}}} {
  557. fix_testname testname
  558. uplevel do_test [list $testname] [list "execsql {$sql}"] [list [list {*}$result]]
  559. }
  560. proc do_catchsql_test {testname sql result} {
  561. fix_testname testname
  562. uplevel do_test [list $testname] [list "catchsql {$sql}"] [list $result]
  563. }
  564. proc do_eqp_test {name sql res} {
  565. uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
  566. }
  567. #-------------------------------------------------------------------------
  568. # Usage: do_select_tests PREFIX ?SWITCHES? TESTLIST
  569. #
  570. # Where switches are:
  571. #
  572. # -errorformat FMTSTRING
  573. # -count
  574. # -query SQL
  575. # -tclquery TCL
  576. # -repair TCL
  577. #
  578. proc do_select_tests {prefix args} {
  579. set testlist [lindex $args end]
  580. set switches [lrange $args 0 end-1]
  581. set errfmt ""
  582. set countonly 0
  583. set tclquery ""
  584. set repair ""
  585. for {set i 0} {$i < [llength $switches]} {incr i} {
  586. set s [lindex $switches $i]
  587. set n [string length $s]
  588. if {$n>=2 && [string equal -length $n $s "-query"]} {
  589. set tclquery [list execsql [lindex $switches [incr i]]]
  590. } elseif {$n>=2 && [string equal -length $n $s "-tclquery"]} {
  591. set tclquery [lindex $switches [incr i]]
  592. } elseif {$n>=2 && [string equal -length $n $s "-errorformat"]} {
  593. set errfmt [lindex $switches [incr i]]
  594. } elseif {$n>=2 && [string equal -length $n $s "-repair"]} {
  595. set repair [lindex $switches [incr i]]
  596. } elseif {$n>=2 && [string equal -length $n $s "-count"]} {
  597. set countonly 1
  598. } else {
  599. error "unknown switch: $s"
  600. }
  601. }
  602. if {$countonly && $errfmt!=""} {
  603. error "Cannot use -count and -errorformat together"
  604. }
  605. set nTestlist [llength $testlist]
  606. if {$nTestlist%3 || $nTestlist==0 } {
  607. error "SELECT test list contains [llength $testlist] elements"
  608. }
  609. eval $repair
  610. foreach {tn sql res} $testlist {
  611. if {$tclquery != ""} {
  612. execsql $sql
  613. uplevel do_test ${prefix}.$tn [list $tclquery] [list [list {*}$res]]
  614. } elseif {$countonly} {
  615. set nRow 0
  616. db eval $sql {incr nRow}
  617. uplevel do_test ${prefix}.$tn [list [list set {} $nRow]] [list $res]
  618. } elseif {$errfmt==""} {
  619. uplevel do_execsql_test ${prefix}.${tn} [list $sql] [list [list {*}$res]]
  620. } else {
  621. set res [list 1 [string trim [format $errfmt {*}$res]]]
  622. uplevel do_catchsql_test ${prefix}.${tn} [list $sql] [list $res]
  623. }
  624. eval $repair
  625. }
  626. }
  627. proc delete_all_data {} {
  628. db eval {SELECT tbl_name AS t FROM sqlite_master WHERE type = 'table'} {
  629. db eval "DELETE FROM '[string map {' ''} $t]'"
  630. }
  631. }
  632. # Run an SQL script.
  633. # Return the number of microseconds per statement.
  634. #
  635. proc speed_trial {name numstmt units sql} {
  636. puts -nonewline [format {%-21.21s } $name...]
  637. flush stdout
  638. set speed [time {sqlite3_exec_nr db $sql}]
  639. set tm [lindex $speed 0]
  640. if {$tm == 0} {
  641. set rate [format %20s "many"]
  642. } else {
  643. set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]]
  644. }
  645. set u2 $units/s
  646. puts [format {%12d uS %s %s} $tm $rate $u2]
  647. global total_time
  648. set total_time [expr {$total_time+$tm}]
  649. lappend ::speed_trial_times $name $tm
  650. }
  651. proc speed_trial_tcl {name numstmt units script} {
  652. puts -nonewline [format {%-21.21s } $name...]
  653. flush stdout
  654. set speed [time {eval $script}]
  655. set tm [lindex $speed 0]
  656. if {$tm == 0} {
  657. set rate [format %20s "many"]
  658. } else {
  659. set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]]
  660. }
  661. set u2 $units/s
  662. puts [format {%12d uS %s %s} $tm $rate $u2]
  663. global total_time
  664. set total_time [expr {$total_time+$tm}]
  665. lappend ::speed_trial_times $name $tm
  666. }
  667. proc speed_trial_init {name} {
  668. global total_time
  669. set total_time 0
  670. set ::speed_trial_times [list]
  671. sqlite3 versdb :memory:
  672. set vers [versdb one {SELECT sqlite_source_id()}]
  673. versdb close
  674. puts "SQLite $vers"
  675. }
  676. proc speed_trial_summary {name} {
  677. global total_time
  678. puts [format {%-21.21s %12d uS TOTAL} $name $total_time]
  679. if { 0 } {
  680. sqlite3 versdb :memory:
  681. set vers [lindex [versdb one {SELECT sqlite_source_id()}] 0]
  682. versdb close
  683. puts "CREATE TABLE IF NOT EXISTS time(version, script, test, us);"
  684. foreach {test us} $::speed_trial_times {
  685. puts "INSERT INTO time VALUES('$vers', '$name', '$test', $us);"
  686. }
  687. }
  688. }
  689. # Run this routine last
  690. #
  691. proc finish_test {} {
  692. catch {db close}
  693. catch {db2 close}
  694. catch {db3 close}
  695. if {0==[info exists ::SLAVE]} { finalize_testing }
  696. }
  697. proc finalize_testing {} {
  698. global sqlite_open_file_count
  699. set omitList [set_test_counter omit_list]
  700. catch {db close}
  701. catch {db2 close}
  702. catch {db3 close}
  703. vfs_unlink_test
  704. sqlite3 db {}
  705. # sqlite3_clear_tsd_memdebug
  706. db close
  707. sqlite3_reset_auto_extension
  708. sqlite3_soft_heap_limit 0
  709. set nTest [incr_ntest]
  710. set nErr [set_test_counter errors]
  711. puts "$nErr errors out of $nTest tests"
  712. if {$nErr>0} {
  713. puts "Failures on these tests: [set_test_counter fail_list]"
  714. }
  715. run_thread_tests 1
  716. if {[llength $omitList]>0} {
  717. puts "Omitted test cases:"
  718. set prec {}
  719. foreach {rec} [lsort $omitList] {
  720. if {$rec==$prec} continue
  721. set prec $rec
  722. puts [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]]
  723. }
  724. }
  725. if {$nErr>0 && ![working_64bit_int]} {
  726. puts "******************************************************************"
  727. puts "N.B.: The version of TCL that you used to build this test harness"
  728. puts "is defective in that it does not support 64-bit integers. Some or"
  729. puts "all of the test failures above might be a result from this defect"
  730. puts "in your TCL build."
  731. puts "******************************************************************"
  732. }
  733. if {$::cmdlinearg(binarylog)} {
  734. vfslog finalize binarylog
  735. }
  736. if {$sqlite_open_file_count} {
  737. puts "$sqlite_open_file_count files were left open"
  738. incr nErr
  739. }
  740. if {[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]>0 ||
  741. [sqlite3_memory_used]>0} {
  742. puts "Unfreed memory: [sqlite3_memory_used] bytes in\
  743. [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations"
  744. incr nErr
  745. ifcapable memdebug||mem5||(mem3&&debug) {
  746. puts "Writing unfreed memory log to \"./memleak.txt\""
  747. sqlite3_memdebug_dump ./memleak.txt
  748. }
  749. } else {
  750. puts "All memory allocations freed - no leaks"
  751. ifcapable memdebug||mem5 {
  752. sqlite3_memdebug_dump ./memusage.txt
  753. }
  754. }
  755. show_memstats
  756. puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
  757. puts "Current memory usage: [sqlite3_memory_highwater] bytes"
  758. if {[info commands sqlite3_memdebug_malloc_count] ne ""} {
  759. puts "Number of malloc() : [sqlite3_memdebug_malloc_count] calls"
  760. }
  761. if {$::cmdlinearg(malloctrace)} {
  762. puts "Writing mallocs.sql..."
  763. memdebug_log_sql
  764. sqlite3_memdebug_log stop
  765. sqlite3_memdebug_log clear
  766. if {[sqlite3_memory_used]>0} {
  767. puts "Writing leaks.sql..."
  768. sqlite3_memdebug_log sync
  769. memdebug_log_sql leaks.sql
  770. }
  771. }
  772. foreach f [glob -nocomplain test.db-*-journal] {
  773. forcedelete $f
  774. }
  775. foreach f [glob -nocomplain test.db-mj*] {
  776. forcedelete $f
  777. }
  778. exit [expr {$nErr>0}]
  779. }
  780. # Display memory statistics for analysis and debugging purposes.
  781. #
  782. proc show_memstats {} {
  783. set x [sqlite3_status SQLITE_STATUS_MEMORY_USED 0]
  784. set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
  785. set val [format {now %10d max %10d max-size %10d} \
  786. [lindex $x 1] [lindex $x 2] [lindex $y 2]]
  787. puts "Memory used: $val"
  788. set x [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0]
  789. set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
  790. puts "Allocation count: $val"
  791. set x [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0]
  792. set y [sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 0]
  793. set val [format {now %10d max %10d max-size %10d} \
  794. [lindex $x 1] [lindex $x 2] [lindex $y 2]]
  795. puts "Page-cache used: $val"
  796. set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0]
  797. set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
  798. puts "Page-cache overflow: $val"
  799. set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0]
  800. set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
  801. puts "Scratch memory used: $val"
  802. set x [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0]
  803. set y [sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 0]
  804. set val [format {now %10d max %10d max-size %10d} \
  805. [lindex $x 1] [lindex $x 2] [lindex $y 2]]
  806. puts "Scratch overflow: $val"
  807. ifcapable yytrackmaxstackdepth {
  808. set x [sqlite3_status SQLITE_STATUS_PARSER_STACK 0]
  809. set val [format { max %10d} [lindex $x 2]]
  810. puts "Parser stack depth: $val"
  811. }
  812. }
  813. # A procedure to execute SQL
  814. #
  815. proc execsql {sql {db db}} {
  816. # puts "SQL = $sql"
  817. uplevel [list $db eval $sql]
  818. }
  819. # Execute SQL and catch exceptions.
  820. #
  821. proc catchsql {sql {db db}} {
  822. # puts "SQL = $sql"
  823. set r [catch [list uplevel [list $db eval $sql]] msg]
  824. lappend r $msg
  825. return $r
  826. }
  827. # Do an VDBE code dump on the SQL given
  828. #
  829. proc explain {sql {db db}} {
  830. puts ""
  831. puts "addr opcode p1 p2 p3 p4 p5 #"
  832. puts "---- ------------ ------ ------ ------ --------------- -- -"
  833. $db eval "explain $sql" {} {
  834. puts [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \
  835. $addr $opcode $p1 $p2 $p3 $p4 $p5 $comment
  836. ]
  837. }
  838. }
  839. # Show the VDBE program for an SQL statement but omit the Trace
  840. # opcode at the beginning. This procedure can be used to prove
  841. # that different SQL statements generate exactly the same VDBE code.
  842. #
  843. proc explain_no_trace {sql} {
  844. set tr [db eval "EXPLAIN $sql"]
  845. return [lrange $tr 7 end]
  846. }
  847. # Another procedure to execute SQL. This one includes the field
  848. # names in the returned list.
  849. #
  850. proc execsql2 {sql} {
  851. set result {}
  852. db eval $sql data {
  853. foreach f $data(*) {
  854. lappend result $f $data($f)
  855. }
  856. }
  857. return $result
  858. }
  859. # Use the non-callback API to execute multiple SQL statements
  860. #
  861. proc stepsql {dbptr sql} {
  862. set sql [string trim $sql]
  863. set r 0
  864. while {[string length $sql]>0} {
  865. if {[catch {sqlite3_prepare $dbptr $sql -1 sqltail} vm]} {
  866. return [list 1 $vm]
  867. }
  868. set sql [string trim $sqltail]
  869. # while {[sqlite_step $vm N VAL COL]=="SQLITE_ROW"} {
  870. # foreach v $VAL {lappend r $v}
  871. # }
  872. while {[sqlite3_step $vm]=="SQLITE_ROW"} {
  873. for {set i 0} {$i<[sqlite3_data_count $vm]} {incr i} {
  874. lappend r [sqlite3_column_text $vm $i]
  875. }
  876. }
  877. if {[catch {sqlite3_finalize $vm} errmsg]} {
  878. return [list 1 $errmsg]
  879. }
  880. }
  881. return $r
  882. }
  883. # Do an integrity check of the entire database
  884. #
  885. proc integrity_check {name {db db}} {
  886. ifcapable integrityck {
  887. do_test $name [list execsql {PRAGMA integrity_check} $db] {ok}
  888. }
  889. }
  890. # Return true if the SQL statement passed as the second argument uses a
  891. # statement transaction.
  892. #
  893. proc sql_uses_stmt {db sql} {
  894. set stmt [sqlite3_prepare $db $sql -1 dummy]
  895. set uses [uses_stmt_journal $stmt]
  896. sqlite3_finalize $stmt
  897. return $uses
  898. }
  899. proc fix_ifcapable_expr {expr} {
  900. set ret ""
  901. set state 0
  902. for {set i 0} {$i < [string length $expr]} {incr i} {
  903. set char [string range $expr $i $i]
  904. set newstate [expr {[string is alnum $char] || $char eq "_"}]
  905. if {$newstate && !$state} {
  906. append ret {$::sqlite_options(}
  907. }
  908. if {!$newstate && $state} {
  909. append ret )
  910. }
  911. append ret $char
  912. set state $newstate
  913. }
  914. if {$state} {append ret )}
  915. return $ret
  916. }
  917. # Evaluate a boolean expression of capabilities. If true, execute the
  918. # code. Omit the code if false.
  919. #
  920. proc ifcapable {expr code {else ""} {elsecode ""}} {
  921. #regsub -all {[a-z_0-9]+} $expr {$::sqlite_options(&)} e2
  922. set e2 [fix_ifcapable_expr $expr]
  923. if ($e2) {
  924. set c [catch {uplevel 1 $code} r]
  925. } else {
  926. set c [catch {uplevel 1 $elsecode} r]
  927. }
  928. return -code $c $r
  929. }
  930. # This proc execs a seperate process that crashes midway through executing
  931. # the SQL script $sql on database test.db.
  932. #
  933. # The crash occurs during a sync() of file $crashfile. When the crash
  934. # occurs a random subset of all unsynced writes made by the process are
  935. # written into the files on disk. Argument $crashdelay indicates the
  936. # number of file syncs to wait before crashing.
  937. #
  938. # The return value is a list of two elements. The first element is a
  939. # boolean, indicating whether or not the process actually crashed or
  940. # reported some other error. The second element in the returned list is the
  941. # error message. This is "child process exited abnormally" if the crash
  942. # occured.
  943. #
  944. # crashsql -delay CRASHDELAY -file CRASHFILE ?-blocksize BLOCKSIZE? $sql
  945. #
  946. proc crashsql {args} {
  947. set blocksize ""
  948. set crashdelay 1
  949. set prngseed 0
  950. set tclbody {}
  951. set crashfile ""
  952. set dc ""
  953. set sql [lindex $args end]
  954. for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} {
  955. set z [lindex $args $ii]
  956. set n [string length $z]
  957. set z2 [lindex $args [expr $ii+1]]
  958. if {$n>1 && [string first $z -delay]==0} {set crashdelay $z2} \
  959. elseif {$n>1 && [string first $z -seed]==0} {set prngseed $z2} \
  960. elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \
  961. elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \
  962. elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \
  963. elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" } \
  964. else { error "Unrecognized option: $z" }
  965. }
  966. if {$crashfile eq ""} {
  967. error "Compulsory option -file missing"
  968. }
  969. # $crashfile gets compared to the native filename in
  970. # cfSync(), which can be different then what TCL uses by
  971. # default, so here we force it to the "nativename" format.
  972. set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfile]]]
  973. set f [open crash.tcl w]
  974. puts $f "sqlite3_crash_enable 1"
  975. puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile"
  976. puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
  977. puts $f "sqlite3 db test.db -vfs crash"
  978. # This block sets the cache size of the main database to 10
  979. # pages. This is done in case the build is configured to omit
  980. # "PRAGMA cache_size".
  981. puts $f {db eval {SELECT * FROM sqlite_master;}}
  982. puts $f {set bt [btree_from_db db]}
  983. puts $f {btree_set_cache_size $bt 10}
  984. if {$prngseed} {
  985. set seed [expr {$prngseed%10007+1}]
  986. # puts seed=$seed
  987. puts $f "db eval {SELECT randomblob($seed)}"
  988. }
  989. if {[string length $tclbody]>0} {
  990. puts $f $tclbody
  991. }
  992. if {[string length $sql]>0} {
  993. puts $f "db eval {"
  994. puts $f "$sql"
  995. puts $f "}"
  996. }
  997. close $f
  998. set r [catch {
  999. exec [info nameofexec] crash.tcl >@stdout
  1000. } msg]
  1001. # Windows/ActiveState TCL returns a slightly different
  1002. # error message. We map that to the expected message
  1003. # so that we don't have to change all of the test
  1004. # cases.
  1005. if {$::tcl_platform(platform)=="windows"} {
  1006. if {$msg=="child killed: unknown signal"} {
  1007. set msg "child process exited abnormally"
  1008. }
  1009. }
  1010. lappend r $msg
  1011. }
  1012. # Usage: do_ioerr_test <test number> <options...>
  1013. #
  1014. # This proc is used to implement test cases that check that IO errors
  1015. # are correctly handled. The first argument, <test number>, is an integer
  1016. # used to name the tests executed by this proc. Options are as follows:
  1017. #
  1018. # -tclprep TCL script to run to prepare test.
  1019. # -sqlprep SQL script to run to prepare test.
  1020. # -tclbody TCL script to run with IO error simulation.
  1021. # -sqlbody TCL script to run with IO error simulation.
  1022. # -exclude List of 'N' values not to test.
  1023. # -erc Use extended result codes
  1024. # -persist Make simulated I/O errors persistent
  1025. # -start Value of 'N' to begin with (default 1)
  1026. #
  1027. # -cksum Boolean. If true, test that the database does
  1028. # not change during the execution of the test case.
  1029. #
  1030. proc do_ioerr_test {testname args} {
  1031. set ::ioerropts(-start) 1
  1032. set ::ioerropts(-cksum) 0
  1033. set ::ioerropts(-erc) 0
  1034. set ::ioerropts(-count) 100000000
  1035. set ::ioerropts(-persist) 1
  1036. set ::ioerropts(-ckrefcount) 0
  1037. set ::ioerropts(-restoreprng) 1
  1038. array set ::ioerropts $args
  1039. # TEMPORARY: For 3.5.9, disable testing of extended result codes. There are
  1040. # a couple of obscure IO errors that do not return them.
  1041. set ::ioerropts(-erc) 0
  1042. set ::go 1
  1043. #reset_prng_state
  1044. save_prng_state
  1045. for {set n $::ioerropts(-start)} {$::go} {incr n} {
  1046. set ::TN $n
  1047. incr ::ioerropts(-count) -1
  1048. if {$::ioerropts(-count)<0} break
  1049. # Skip this IO error if it was specified with the "-exclude" option.
  1050. if {[info exists ::ioerropts(-exclude)]} {
  1051. if {[lsearch $::ioerropts(-exclude) $n]!=-1} continue
  1052. }
  1053. if {$::ioerropts(-restoreprng)} {
  1054. restore_prng_state
  1055. }
  1056. # Delete the files test.db and test2.db, then execute the TCL and
  1057. # SQL (in that order) to prepare for the test case.
  1058. do_test $testname.$n.1 {
  1059. set ::sqlite_io_error_pending 0
  1060. catch {db close}
  1061. catch {db2 close}
  1062. catch {forcedelete test.db}
  1063. catch {forcedelete test.db-journal}
  1064. catch {forcedelete test2.db}
  1065. catch {forcedelete test2.db-journal}
  1066. set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
  1067. sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
  1068. if {[info exists ::ioerropts(-tclprep)]} {
  1069. eval $::ioerropts(-tclprep)
  1070. }
  1071. if {[info exists ::ioerropts(-sqlprep)]} {
  1072. execsql $::ioerropts(-sqlprep)
  1073. }
  1074. expr 0
  1075. } {0}
  1076. # Read the 'checksum' of the database.
  1077. if {$::ioerropts(-cksum)} {
  1078. set checksum [cksum]
  1079. }
  1080. # Set the Nth IO error to fail.
  1081. do_test $testname.$n.2 [subst {
  1082. set ::sqlite_io_error_persist $::ioerropts(-persist)
  1083. set ::sqlite_io_error_pending $n
  1084. }] $n
  1085. # Create a single TCL script from the TCL and SQL specified
  1086. # as the body of the test.
  1087. set ::ioerrorbody {}
  1088. if {[info exists ::ioerropts(-tclbody)]} {
  1089. append ::ioerrorbody "$::ioerropts(-tclbody)\n"
  1090. }
  1091. if {[info exists ::ioerropts(-sqlbody)]} {
  1092. append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}"
  1093. }
  1094. # Execute the TCL Script created in the above block. If
  1095. # there are at least N IO operations performed by SQLite as
  1096. # a result of the script, the Nth will fail.
  1097. do_test $testname.$n.3 {
  1098. set ::sqlite_io_error_hit 0
  1099. set ::sqlite_io_error_hardhit 0
  1100. set r [catch $::ioerrorbody msg]
  1101. set ::errseen $r
  1102. set rc [sqlite3_errcode $::DB]
  1103. if {$::ioerropts(-erc)} {
  1104. # If we are in extended result code mode, make sure all of the
  1105. # IOERRs we get back really do have their extended code values.
  1106. # If an extended result code is returned, the sqlite3_errcode
  1107. # TCLcommand will return a string of the form: SQLITE_IOERR+nnnn
  1108. # where nnnn is a number
  1109. if {[regexp {^SQLITE_IOERR} $rc] && ![regexp {IOERR\+\d} $rc]} {
  1110. return $rc
  1111. }
  1112. } else {
  1113. # If we are not in extended result code mode, make sure no
  1114. # extended error codes are returned.
  1115. if {[regexp {\+\d} $rc]} {
  1116. return $rc
  1117. }
  1118. }
  1119. # The test repeats as long as $::go is non-zero. $::go starts out
  1120. # as 1. When a test runs to completion without hitting an I/O
  1121. # error, that means there is no point in continuing with this test
  1122. # case so set $::go to zero.
  1123. #
  1124. if {$::sqlite_io_error_pending>0} {
  1125. set ::go 0
  1126. set q 0
  1127. set ::sqlite_io_error_pending 0
  1128. } else {
  1129. set q 1
  1130. }
  1131. set s [expr $::sqlite_io_error_hit==0]
  1132. if {$::sqlite_io_error_hit>$::sqlite_io_error_hardhit && $r==0} {
  1133. set r 1
  1134. }
  1135. set ::sqlite_io_error_hit 0
  1136. # One of two things must have happened. either
  1137. # 1. We never hit the IO error and the SQL returned OK
  1138. # 2. An IO error was hit and the SQL failed
  1139. #
  1140. #puts "s=$s r=$r q=$q"
  1141. expr { ($s && !$r && !$q) || (!$s && $r && $q) }
  1142. } {1}
  1143. set ::sqlite_io_error_hit 0
  1144. set ::sqlite_io_error_pending 0
  1145. # Check that no page references were leaked. There should be
  1146. # a single reference if there is still an active transaction,
  1147. # or zero otherwise.
  1148. #
  1149. # UPDATE: If the IO error occurs after a 'BEGIN' but before any
  1150. # locks are established on database files (i.e. if the error
  1151. # occurs while attempting to detect a hot-journal file), then
  1152. # there may 0 page references and an active transaction according
  1153. # to [sqlite3_get_autocommit].
  1154. #
  1155. if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-ckrefcount)} {
  1156. do_test $testname.$n.4 {
  1157. set bt [btree_from_db db]
  1158. db_enter db
  1159. array set stats [btree_pager_stats $bt]
  1160. db_leave db
  1161. set nRef $stats(ref)
  1162. expr {$nRef == 0 || ([sqlite3_get_autocommit db]==0 && $nRef == 1)}
  1163. } {1}
  1164. }
  1165. # If there is an open database handle and no open transaction,
  1166. # and the pager is not running in exclusive-locking mode,
  1167. # check that the pager is in "unlocked" state. Theoretically,
  1168. # if a call to xUnlock() failed due to an IO error the underlying
  1169. # file may still be locked.
  1170. #
  1171. ifcapable pragma {
  1172. if { [info commands db] ne ""
  1173. && $::ioerropts(-ckrefcount)
  1174. && [db one {pragma locking_mode}] eq "normal"
  1175. && [sqlite3_get_autocommit db]
  1176. } {
  1177. do_test $testname.$n.5 {
  1178. set bt [btree_from_db db]
  1179. db_enter db
  1180. array set stats [btree_pager_stats $bt]
  1181. db_leave db
  1182. set stats(state)
  1183. } 0
  1184. }
  1185. }
  1186. # If an IO error occured, then the checksum of the database should
  1187. # be the same as before the script that caused the IO error was run.
  1188. #
  1189. if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-cksum)} {
  1190. do_test $testname.$n.6 {
  1191. catch {db close}
  1192. catch {db2 close}
  1193. set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
  1194. cksum
  1195. } $checksum
  1196. }
  1197. set ::sqlite_io_error_hardhit 0
  1198. set ::sqlite_io_error_pending 0
  1199. if {[info exists ::ioerropts(-cleanup)]} {
  1200. catch $::ioerropts(-cleanup)
  1201. }
  1202. }
  1203. set ::sqlite_io_error_pending 0
  1204. set ::sqlite_io_error_persist 0
  1205. unset ::ioerropts
  1206. }
  1207. # Return a checksum based on the contents of the main database associated
  1208. # with connection $db
  1209. #
  1210. proc cksum {{db db}} {
  1211. set txt [$db eval {
  1212. SELECT name, type, sql FROM sqlite_master order by name
  1213. }]\n
  1214. foreach tbl [$db eval {
  1215. SELECT name FROM sqlite_master WHERE type='table' order by name
  1216. }] {
  1217. append txt [$db eval "SELECT * FROM $tbl"]\n
  1218. }
  1219. foreach prag {default_synchronous default_cache_size} {
  1220. append txt $prag-[$db eval "PRAGMA $prag"]\n
  1221. }
  1222. set cksum [string length $txt]-[md5 $txt]
  1223. # puts $cksum-[file size test.db]
  1224. return $cksum
  1225. }
  1226. # Generate a checksum based on the contents of the main and temp tables
  1227. # database $db. If the checksum of two databases is the same, and the
  1228. # integrity-check passes for both, the two databases are identical.
  1229. #
  1230. proc allcksum {{db db}} {
  1231. set ret [list]
  1232. ifcapable tempdb {
  1233. set sql {
  1234. SELECT name FROM sqlite_master WHERE type = 'table' UNION
  1235. SELECT name FROM sqlite_temp_master WHERE type = 'table' UNION
  1236. SELECT 'sqlite_master' UNION
  1237. SELECT 'sqlite_temp_master' ORDER BY 1
  1238. }
  1239. } else {
  1240. set sql {
  1241. SELECT name FROM sqlite_master WHERE type = 'table' UNION
  1242. SELECT 'sqlite_master' ORDER BY 1
  1243. }
  1244. }
  1245. set tbllist [$db eval $sql]
  1246. set txt {}
  1247. foreach tbl $tbllist {
  1248. append txt [$db eval "SELECT * FROM $tbl"]
  1249. }
  1250. foreach prag {default_cache_size} {
  1251. append txt $prag-[$db eval "PRAGMA $prag"]\n
  1252. }
  1253. # puts txt=$txt
  1254. return [md5 $txt]
  1255. }
  1256. # Generate a checksum based on the contents of a single database with
  1257. # a database connection. The name of the database is $dbname.
  1258. # Examples of $dbname are "temp" or "main".
  1259. #
  1260. proc dbcksum {db dbname} {
  1261. if {$dbname=="temp"} {
  1262. set master sqlite_temp_master
  1263. } else {
  1264. set master $dbname.sqlite_master
  1265. }
  1266. set alltab [$db eval "SELECT name FROM $master WHERE type='table'"]
  1267. set txt [$db eval "SELECT * FROM $master"]\n
  1268. foreach tab $alltab {
  1269. append txt [$db eval "SELECT * FROM $dbname.$tab"]\n
  1270. }
  1271. return [md5 $txt]
  1272. }
  1273. proc memdebug_log_sql {{filename mallocs.sql}} {
  1274. set data [sqlite3_memdebug_log dump]
  1275. set nFrame [expr [llength [lindex $data 0]]-2]
  1276. if {$nFrame < 0} { return "" }
  1277. set database temp
  1278. set tbl "CREATE TABLE ${database}.malloc(zTest, nCall, nByte, lStack);"
  1279. set sql ""
  1280. foreach e $data {
  1281. set nCall [lindex $e 0]
  1282. set nByte [lindex $e 1]
  1283. set lStack [lrange $e 2 end]
  1284. append sql "INSERT INTO ${database}.malloc VALUES"
  1285. append sql "('test', $nCall, $nByte, '$lStack');\n"
  1286. foreach f $lStack {
  1287. set frames($f) 1
  1288. }
  1289. }
  1290. set tbl2 "CREATE TABLE ${database}.frame(frame INTEGER PRIMARY KEY, line);\n"
  1291. set tbl3 "CREATE TABLE ${database}.file(name PRIMARY KEY, content);\n"
  1292. foreach f [array names frames] {
  1293. set addr [format %x $f]
  1294. set cmd "addr2line -e [info nameofexec] $addr"
  1295. set line [eval exec $cmd]
  1296. append sql "INSERT INTO ${database}.frame VALUES($f, '$line');\n"
  1297. set file [lindex [split $line :] 0]
  1298. set files($file) 1
  1299. }
  1300. foreach f [array names files] {
  1301. set contents ""
  1302. catch {
  1303. set fd [open $f]
  1304. set contents [read $fd]
  1305. close $fd
  1306. }
  1307. set contents [string map {' ''} $contents]
  1308. append sql "INSERT INTO ${database}.file VALUES('$f', '$contents');\n"
  1309. }
  1310. set fd [open $filename w]
  1311. puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
  1312. close $fd
  1313. }
  1314. # Drop all tables in database [db]
  1315. proc drop_all_tables {{db db}} {
  1316. ifcapable trigger&&foreignkey {
  1317. set pk [$db one "PRAGMA foreign_keys"]
  1318. $db eval "PRAGMA foreign_keys = OFF"
  1319. }
  1320. foreach {idx name file} [db eval {PRAGMA database_list}] {
  1321. if {$idx==1} {
  1322. set master sqlite_temp_master
  1323. } else {
  1324. set master $name.sqlite_master
  1325. }
  1326. foreach {t type} [$db eval "
  1327. SELECT name, type FROM $master
  1328. WHERE type IN('table', 'view') AND name NOT LIKE 'sqliteX_%' ESCAPE 'X'
  1329. "] {
  1330. $db eval "DROP $type \"$t\""
  1331. }
  1332. }
  1333. ifcapable trigger&&foreignkey {
  1334. $db eval "PRAGMA foreign_keys = $pk"
  1335. }
  1336. }
  1337. #-------------------------------------------------------------------------
  1338. # If a test script is executed with global variable $::G(perm:name) set to
  1339. # "wal", then the tests are run in WAL mode. Otherwise, they should be run
  1340. # in rollback mode. The following Tcl procs are used to make this less
  1341. # intrusive:
  1342. #
  1343. # wal_set_journal_mode ?DB?
  1344. #
  1345. # If running a WAL test, execute "PRAGMA journal_mode = wal" using
  1346. # connection handle DB. Otherwise, this command is a no-op.
  1347. #
  1348. # wal_check_journal_mode TESTNAME ?DB?
  1349. #
  1350. # If running a WAL test, execute a tests case that fails if the main
  1351. # database for connection handle DB is not currently a WAL database.
  1352. # Otherwise (if not running a WAL permutation) this is a no-op.
  1353. #
  1354. # wal_is_wal_mode
  1355. #
  1356. # Returns true if this test should be run in WAL mode. False otherwise.
  1357. #
  1358. proc wal_is_wal_mode {} {
  1359. expr {[permutation] eq "wal"}
  1360. }
  1361. proc wal_set_journal_mode {{db db}} {
  1362. if { [wal_is_wal_mode] } {
  1363. $db eval "PRAGMA journal_mode = WAL"
  1364. }
  1365. }
  1366. proc wal_check_journal_mode {testname {db db}} {
  1367. if { [wal_is_wal_mode] } {
  1368. $db eval { SELECT * FROM sqlite_master }
  1369. do_test $testname [list $db eval "PRAGMA main.journal_mode"] {wal}
  1370. }
  1371. }
  1372. proc permutation {} {
  1373. set perm ""
  1374. catch {set perm $::G(perm:name)}
  1375. set perm
  1376. }
  1377. proc presql {} {
  1378. set presql ""
  1379. catch {set presql $::G(perm:presql)}
  1380. set presql
  1381. }
  1382. #-------------------------------------------------------------------------
  1383. #
  1384. proc slave_test_script {script} {
  1385. # Create the interpreter used to run the test script.
  1386. interp create tinterp
  1387. # Populate some global variables that tester.tcl expects to see.
  1388. foreach {var value} [list \
  1389. ::argv0 $::argv0 \
  1390. ::argv {} \
  1391. ::SLAVE 1 \
  1392. ] {
  1393. interp eval tinterp [list set $var $value]
  1394. }
  1395. # The alias used to access the global test counters.
  1396. tinterp alias set_test_counter set_test_counter
  1397. # Set up the ::cmdlinearg array in the slave.
  1398. interp eval tinterp [list array set ::cmdlinearg [array get ::cmdlinearg]]
  1399. # Set up the ::G array in the slave.
  1400. interp eval tinterp [list array set ::G [array get ::G]]
  1401. # Load the various test interfaces implemented in C.
  1402. load_testfixture_extensions tinterp
  1403. # Run the test script.
  1404. interp eval tinterp $script
  1405. # Check if the interpreter call [run_thread_tests]
  1406. if { [interp eval tinterp {info exists ::run_thread_tests_called}] } {
  1407. set ::run_thread_tests_called 1
  1408. }
  1409. # Delete the interpreter used to run the test script.
  1410. interp delete tinterp
  1411. }
  1412. proc slave_test_file {zFile} {
  1413. set tail [file tail $zFile]
  1414. if {[info exists ::G(start:permutation)]} {
  1415. if {[permutation] != $::G(start:permutation)} return
  1416. unset ::G(start:permutation)
  1417. }
  1418. if {[info exists ::G(start:file)]} {
  1419. if {$tail != $::G(start:file) && $tail!="$::G(start:file).test"} return
  1420. unset ::G(start:file)
  1421. }
  1422. # Remember the value of the shared-cache setting. So that it is possible
  1423. # to check afterwards that it was not modified by the test script.
  1424. #
  1425. ifcapable shared_cache { set scs [sqlite3_enable_shared_cache] }
  1426. # Run the test script in a slave interpreter.
  1427. #
  1428. unset -nocomplain ::run_thread_tests_called
  1429. reset_prng_state
  1430. set ::sqlite_open_file_count 0
  1431. set time [time { slave_test_script [list source $zFile] }]
  1432. set ms [expr [lindex $time 0] / 1000]
  1433. # Test that all files opened by the test script were closed. Omit this
  1434. # if the test script has "thread" in its name. The open file counter
  1435. # is not thread-safe.
  1436. #
  1437. if {[info exists ::run_thread_tests_called]==0} {
  1438. do_test ${tail}-closeallfiles { expr {$::sqlite_open_file_count>0} } {0}
  1439. }
  1440. set ::sqlite_open_file_count 0
  1441. # Test that the global "shared-cache" setting was not altered by
  1442. # the test script.
  1443. #
  1444. ifcapable shared_cache {
  1445. set res [expr {[sqlite3_enable_shared_cache] == $scs}]
  1446. do_test ${tail}-sharedcachesetting [list set {} $res] 1
  1447. }
  1448. # Add some info to the output.
  1449. #
  1450. puts "Time: $tail $ms ms"
  1451. show_memstats
  1452. }
  1453. # Open a new connection on database test.db and execute the SQL script
  1454. # supplied as an argument. Before returning, close the new conection and
  1455. # restore the 4 byte fields starting at header offsets 28, 92 and 96
  1456. # to the values they held before the SQL was executed. This simulates
  1457. # a write by a pre-3.7.0 client.
  1458. #
  1459. proc sql36231 {sql} {
  1460. set B [hexio_read test.db 92 8]
  1461. set A [hexio_read test.db 28 4]
  1462. sqlite3 db36231 test.db
  1463. catch { db36231 func a_string a_string }
  1464. execsql $sql db36231
  1465. db36231 close
  1466. hexio_write test.db 28 $A
  1467. hexio_write test.db 92 $B
  1468. return ""
  1469. }
  1470. proc db_save {} {
  1471. foreach f [glob -nocomplain sv_test.db*] { forcedelete $f }
  1472. foreach f [glob -nocomplain test.db*] {
  1473. set f2 "sv_$f"
  1474. forcecopy $f $f2
  1475. }
  1476. }
  1477. proc db_save_and_close {} {
  1478. db_save
  1479. catch { db close }
  1480. return ""
  1481. }
  1482. proc db_restore {} {
  1483. foreach f [glob -nocomplain test.db*] { forcedelete $f }
  1484. foreach f2 [glob -nocomplain sv_test.db*] {
  1485. set f [string range $f2 3 end]
  1486. forcecopy $f2 $f
  1487. }
  1488. }
  1489. proc db_restore_and_reopen {{dbfile test.db}} {
  1490. catch { db close }
  1491. db_restore
  1492. sqlite3 db $dbfile
  1493. }
  1494. proc db_delete_and_reopen {{file test.db}} {
  1495. catch { db close }
  1496. foreach f [glob -nocomplain test.db*] { forcedelete $f }
  1497. sqlite3 db $file
  1498. }
  1499. # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set
  1500. # to non-zero, then set the global variable $AUTOVACUUM to 1.
  1501. set AUTOVACUUM $sqlite_options(default_autovacuum)
  1502. # Make sure the FTS enhanced query syntax is disabled.
  1503. set sqlite_fts3_enable_parentheses 0
  1504. source $testdir/thread_common.tcl
  1505. source $testdir/malloc_common.tcl