1# 2007 September 7 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# 12# $Id: thread001.test,v 1.8 2009/02/04 11:57:46 danielk1977 Exp $ 13 14set testdir [file dirname $argv0] 15 16source $testdir/tester.tcl 17ifcapable !mutex { 18 return 19} 20source $testdir/thread_common.tcl 21if {[info commands sqlthread] eq ""} { 22 return 23} 24 25set ::enable_shared_cache [sqlite3_enable_shared_cache] 26 27set ::NTHREAD 10 28 29# Run this test three times: 30# 31# 1) All threads use the same database handle. 32# 2) All threads use their own database handles. 33# 3) All threads use their own database handles, shared-cache is enabled. 34# 35# 36# 37foreach {tn same_db shared_cache} [list \ 38 1 1 0 \ 39 2 0 0 \ 40 3 0 1 \ 41] { 42 # Empty the database. 43 # 44 catchsql { DROP TABLE ab; } 45 46 do_test thread001.$tn.0 { 47 db close 48 sqlite3_enable_shared_cache $shared_cache 49 sqlite3_enable_shared_cache $shared_cache 50 } $shared_cache 51 sqlite3 db test.db -fullmutex 1 52 53 set dbconfig "" 54 if {$same_db} { 55 set dbconfig [list set ::DB [sqlite3_connection_pointer db]] 56 } 57 58 # Set up a database and a schema. The database contains a single 59 # table with two columns. The first column ("a") is an INTEGER PRIMARY 60 # KEY. The second contains the md5sum of all rows in the table with 61 # a smaller value stored in column "a". 62 # 63 do_test thread001.$tn.1 { 64 execsql { 65 CREATE TABLE ab(a INTEGER PRIMARY KEY, b); 66 CREATE INDEX ab_i ON ab(b); 67 INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab; 68 SELECT count(*) FROM ab; 69 } 70 } {1} 71 do_test thread001.$tn.2 { 72 execsql { 73 SELECT 74 (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) == 75 (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab)) 76 } 77 } {1} 78 do_test thread001.$tn.3 { 79 execsql { PRAGMA integrity_check } 80 } {ok} 81 82 set thread_program { 83 #sqlthread parent {puts STARTING..} 84 set needToClose 0 85 if {![info exists ::DB]} { 86 set ::DB [sqlthread open test.db] 87 #sqlthread parent "puts \"OPEN $::DB\"" 88 set needToClose 1 89 } 90 91 for {set i 0} {$i < 100} {incr i} { 92 # Test that the invariant is true. 93 do_test t1 { 94 execsql { 95 SELECT 96 (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) == 97 (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab)) 98 } 99 } {1} 100 101 # Add another row to the database. 102 execsql { INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab } 103 } 104 105 if {$needToClose} { 106 #sqlthread parent "puts \"CLOSE $::DB\"" 107 sqlite3_close $::DB 108 } 109 #sqlthread parent "puts \"DONE\"" 110 111 list OK 112 } 113 114 # Kick off $::NTHREAD threads: 115 # 116 array unset finished 117 for {set i 0} {$i < $::NTHREAD} {incr i} { 118 thread_spawn finished($i) $dbconfig $thread_procs $thread_program 119 } 120 121 # Wait for all threads to finish, then check they all returned "OK". 122 # 123 for {set i 0} {$i < $::NTHREAD} {incr i} { 124 if {![info exists finished($i)]} { 125 vwait finished($i) 126 } 127 do_test thread001.$tn.4.$i { 128 set ::finished($i) 129 } OK 130 } 131 132 # Check the database still looks Ok. 133 # 134 do_test thread001.$tn.5 { 135 execsql { SELECT count(*) FROM ab; } 136 } [expr {1 + $::NTHREAD*100}] 137 do_test thread001.$tn.6 { 138 execsql { 139 SELECT 140 (SELECT md5sum(a, b) FROM ab WHERE a < (SELECT max(a) FROM ab)) == 141 (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab)) 142 } 143 } {1} 144 do_test thread001.$tn.7 { 145 execsql { PRAGMA integrity_check } 146 } {ok} 147} 148 149sqlite3_enable_shared_cache $::enable_shared_cache 150finish_test 151