# 2007 September 7 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # $Id: thread001.test,v 1.1 2007/09/07 11:29:25 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl if {[info commands sqlthread] eq ""} { puts "Skipping thread-safety tests - not running a threadsafe unix build" finish_test return } # Set up a database and a schema. The database contains a single # table with two columns. The first column ("a") is an INTEGER PRIMARY # KEY. The second contains the md5sum of all rows in the table with # a smaller value stored in column "a". # do_test thread001.1 { execsql { CREATE TABLE ab(a INTEGER PRIMARY KEY, b); CREATE INDEX ab_i ON ab(b); INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab; SELECT count(*) FROM ab; } } {1} do_test thread001.2 { execsql { SELECT (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) == (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab)) } } {1} do_test thread001.3 { execsql { PRAGMA integrity_check } } {ok} set thread_program [format { set ::DB %s # Execute the supplied SQL using database handle $::DB. # proc execsql {sql} { set res [list] set ::STMT [sqlite3_prepare $::DB $sql -1 dummy_tail] while {[sqlite3_step $::STMT] eq "SQLITE_ROW"} { for {set i 0} {$i < [sqlite3_column_count $::STMT]} {incr i} { lappend res [sqlite3_column_text $::STMT 0] } } set rc [sqlite3_finalize $::STMT] if {$rc ne "SQLITE_OK"} { error [sqlite3_errmsg $::DB] } set res } for {set i 0} {$i < 100} {incr i} { # Test that the invariant is true. set val [execsql { SELECT (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) == (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab)) }] if {$val ne "1"} {error "Invariant test failed"} # Add another row to the database. execsql { INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab } } list OK } [sqlite3_connection_pointer db]] # Kick off 10 threads: # array unset finished for {set i 0} {$i < 10} {incr i} { sqlthread spawn finished($i) $thread_program } for {set i 0} {$i < 10} {incr i} { if {![info exists finished($i)]} { vwait finished($i) } do_test thread001.4.$i { set ::finished($i) } OK } do_test thread001.5 { execsql { SELECT count(*) FROM ab; } } {1001} do_test thread001.6 { execsql { SELECT (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) == (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab)) } } {1} do_test thread001.7 { execsql { PRAGMA integrity_check } } {ok} # Give the event-handlers a chance to close any open parent-child pipes. # Otherwise, the test is reported as leaking memory (it has not - it's # just that the memory is freed asynchronously). # after 250 {set abit 0} vwait abit finish_test